提问人:GT 77 提问时间:6/2/2020 最后编辑:songyuanyaoGT 77 更新时间:6/3/2020 访问量:103
当有可用的右值构造函数时,为什么从右值调用类引用构造函数重载?
Why does the class reference constructor overload get called from an rvalue when there's an rvalue constructor available?
问:
此代码
#include <iostream>
struct A
{
A(int i) {std::cout << "int received\n";}
A(A& a) {std::cout << "ref received\n";}
};
int main()
{
int j = 5;
A a = j;
}
意外引发以下编译器错误:
error: invalid initialization of non-const reference of type 'A&' from an rvalue of type 'A'
note: initializing argument 1 of 'A::A(A&)'
note: after user-defined conversion: A::A(int)
当我删除第二个构造函数重载时,一切都按预期工作。我想编译器错误地调用了第二个构造函数而不是第一个构造函数。A(A& a)
为什么会这样?
如何让同时具有引用构造函数和右值构造函数的类协调工作?
我使用GNU GCC。
注意:我还注意到一些奇怪的事情:显然,如果我用 替换该行,一切都按预期工作。然而,这并不令人满意,因为如果我尝试从函数参数初始化对象(例如:调用 with )。A a = j;
A a(j);
void f(A a)
f(j)
答:
A a = j;
执行复制初始化。
直到 C++17,
如果 是类类型,并且 of 类型的 cv 非限定版本不是 或派生自 ,或者如果是非类类型,但类型是类类型,则检查可以从 的类型转换为 (或派生自 if 的类型)的用户定义的转换序列,并通过重载解析选择最佳序列。转换结果(如果使用了转换构造函数)将用于直接初始化对象。
T
other
T
T
T
other
other
T
T
T
prvalue temporary (until C++17)
prvalue expression (since C++17)
The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)
类有一个复制结构,将左值引用为非常量,它不能绑定到临时转换自 .即使是临时的构造也可能被优化:复制构造函数必须可用。A
int
A
让复制构造函数接受左值引用(或添加移动构造函数)将解决这个问题。const
由于 C++17 由于强制复制省略,代码可以正常工作。
这些对象被直接构造到存储中,否则它们将被复制/移动到其中。复制/移动构造函数不需要存在或可访问:
另一方面,执行直接初始化,从直接初始化,复制构造函数不涉及。A a(j);
a
j
评论
j
A(A&)
A(A const&)
A(A&)
A(const A&)