为右值参数隐式生成函数重载?
Implicitly generated function overloads for rvalue argument?
如果之前有人问过这个问题,或者我遗漏了一些微不足道的东西,我很抱歉,但是我不清楚以下参考资料。我理解为什么当函数参数不是引用时允许传递右值而不是左值,但是我不明白当函数参数是 const 引用时允许传递右值而不是左值的原因(这对我来说没有意义)但被禁止当传递一个通常的引用时(逻辑行为)。
假设我有以下代码
struct A
{
explicit A(std::string s) : name{ s } { };
A(const A& a) : name{ a.name } { }
A& operator=(const A& a) { name = a.name; return *this; }
A(A&& a) noexcept : name{} { std::swap(name, a.name); }
A& operator= (A&& a) noexcept { std::swap(name, a.name); return *this; }
void talk() const{ std::cout << name << " says blablabla.\n"; }
private:
std::string name;
};
void f(A a) {}
void g(A& a) {}
void h(const A& a) {}
int main()
{
A a{ "a" };
f(a);
f(A{ "temp" });
g(a);
g(A{ "temp" }); // Compile error
h(a);
h(A{ "temp" });
}
现在,我明白了为什么为 f 隐式生成了 A&& 的重载,但是 A& 和 const A& 的行为让我感到困惑。
- 为什么编译器禁止传递 A&& 而不是 A& 而允许传递 A&& 而不是 A&?
- 这是错误还是功能?
- 如果是一项功能,允许它的原因是什么?
谢谢。
编辑:
建议的问题不完全是我问的。我的问题是,为什么它允许绑定临时对象,即使它是 const。链接的问题问 "why does it forbid when it is not const".
已接受的答案:eerorika 在对他的问题的评论中提供的答案最有道理,即与 pre c++11 的向后兼容性。
I do not understand the reason [passing a rvalue instead of lvalue] is allowed when the function parameter is a const reference
这使得使用复制构造函数从右值复制成为可能。可能还有其他原因,但这是一个非常有用的功能。
Is this a bug or a feature?
在语言中有意指定。
这是一种将昂贵的值传递给函数的方法。它允许绑定到临时对象,因为有时函数的结果也很昂贵,并且您不想通过将每个昂贵的值保存为变量来污染代码...C++ 为您完成,这就是我们获得临时对象的方式。
它增加了一致性:
// Whichever you pick, the code below shall be fine.
//using Value = int;
using Value = std::string;
//using Value = std::vector<std::string>;
Value get_something();
Value process(const Value & text);
void set_something(const Value & name);
set_something(process(get_something());
记住:在过去,没有移动语义。即使有了它,每次将值传递给函数时都移动值也不适合我。
如果之前有人问过这个问题,或者我遗漏了一些微不足道的东西,我很抱歉,但是我不清楚以下参考资料。我理解为什么当函数参数不是引用时允许传递右值而不是左值,但是我不明白当函数参数是 const 引用时允许传递右值而不是左值的原因(这对我来说没有意义)但被禁止当传递一个通常的引用时(逻辑行为)。
假设我有以下代码
struct A
{
explicit A(std::string s) : name{ s } { };
A(const A& a) : name{ a.name } { }
A& operator=(const A& a) { name = a.name; return *this; }
A(A&& a) noexcept : name{} { std::swap(name, a.name); }
A& operator= (A&& a) noexcept { std::swap(name, a.name); return *this; }
void talk() const{ std::cout << name << " says blablabla.\n"; }
private:
std::string name;
};
void f(A a) {}
void g(A& a) {}
void h(const A& a) {}
int main()
{
A a{ "a" };
f(a);
f(A{ "temp" });
g(a);
g(A{ "temp" }); // Compile error
h(a);
h(A{ "temp" });
}
现在,我明白了为什么为 f 隐式生成了 A&& 的重载,但是 A& 和 const A& 的行为让我感到困惑。
- 为什么编译器禁止传递 A&& 而不是 A& 而允许传递 A&& 而不是 A&?
- 这是错误还是功能?
- 如果是一项功能,允许它的原因是什么?
谢谢。
编辑: 建议的问题不完全是我问的。我的问题是,为什么它允许绑定临时对象,即使它是 const。链接的问题问 "why does it forbid when it is not const".
已接受的答案:eerorika 在对他的问题的评论中提供的答案最有道理,即与 pre c++11 的向后兼容性。
I do not understand the reason [passing a rvalue instead of lvalue] is allowed when the function parameter is a const reference
这使得使用复制构造函数从右值复制成为可能。可能还有其他原因,但这是一个非常有用的功能。
Is this a bug or a feature?
在语言中有意指定。
这是一种将昂贵的值传递给函数的方法。它允许绑定到临时对象,因为有时函数的结果也很昂贵,并且您不想通过将每个昂贵的值保存为变量来污染代码...C++ 为您完成,这就是我们获得临时对象的方式。
它增加了一致性:
// Whichever you pick, the code below shall be fine.
//using Value = int;
using Value = std::string;
//using Value = std::vector<std::string>;
Value get_something();
Value process(const Value & text);
void set_something(const Value & name);
set_something(process(get_something());
记住:在过去,没有移动语义。即使有了它,每次将值传递给函数时都移动值也不适合我。