class Foo {
int m_num;
public:
Foo() {}
Foo(int& n) {m_num = n;}
Foo(int&& n) {m_num = n;}
Foo(const Foo& src) {m_num = src.m_num;}
Foo(Foo&& src) {m_num = src.m_num;}
Foo& operator =(const Foo& src) {
m_num = src.m_num;
return *this;
}
Foo& operator =(Foo&& src) {// move
m_num = src.m_num;
return *this;
}
int& operator =(const int& src) {return m_num = src;}
int& operator =(int&& src) {return m_num = src;}
};
为什么当我调用Foo f4(Foo(2));
时调用Foo(int&& n)
构造函数而不是Foo(Foo&& src)
构造函数?
另外,为什么不传递作为右值引用的num调用move构造函数?
例如,Foo f = num
不会调用move构造函数。
int main() {
int&& num = 5;
/*int num{ 5 };*/ // initializer-list
Foo f = num; // custom constructor
f = num; // assignment operator
Foo f2 = 6; // custom move constructor
f2 = 10; // custom move assignment
f2 = f; // assignment operator
Foo f3(f); // custom constructor
// f3(f2); // ERROR
f3 = (f2); // assignment operator
Foo f4(Foo(2));
答案 0 :(得分:2)
在Foo(2)
中,整数是一个右值,并且需要int&&
中的右值引用构造函数。
如果是
Foo f = num; // custom constructor
不调用右值构造函数,因为命名值永远不会被视为右值。您必须致电std::move(num)
才能使其正常工作。
标准以此方式定义它,以避免在命名值意外移动并随后使用时造成混淆的情况。即使该变量是右值引用,您也必须明确说明其移动方式。
根据cppreference,c ++ 17编译器必须忽略的copy / move构造函数(即在这种情况下,它不得调用或要求存在copy / move构造函数,这就是为什么您只能看到int&&
的构造函数):
Foo f4(Foo(2));
这里是cppreference的引号(不如标准引号,但足够接近):
语言规则确保不进行任何复制/移动操作, 甚至在概念上:
在初始化变量时,使用初始化表达式 是与类别相同(忽略cv限定)的类值 变量类型:
T x = T(T(T())); //只需调用一次T的默认构造函数即可初始化x