C++ 移动构造函数和右值引用
为什么当我调用C++ 移动构造函数和右值引用,c++,constructor,move-semantics,C++,Constructor,Move Semantics,为什么当我调用foof4(Foo(2))它调用Foo(int&&n)构造函数而不是Foo(Foo&&src)构造函数? 另外,为什么传递num(一个右值引用)不调用移动构造函数呢? 例如,Foo f=num不调用移动构造函数 class Foo { int m_num; public: Foo() {} Foo(int& n) {m_num = n;} Foo(int&& n) {m_num = n;} Foo(const F
foof4(Foo(2))
它调用Foo(int&&n)
构造函数而不是Foo(Foo&&src)
构造函数?
另外,为什么传递num(一个右值引用)不调用移动构造函数呢?
例如,Foo f=num
不调用移动构造函数
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(2)
中,整数是右值,需要使用int&
中的右值引用构造函数
万一
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));
未调用右值构造函数,因为命名值从未被视为右值。您必须调用std::move(num)
使其工作
该标准以这种方式定义它,以避免在命名值意外移动并随后使用时出现混淆情况。即使变量是右值引用,也必须明确移动
编辑
根据c++17,编译器必须省略的复制/移动构造函数(即,在这种情况下,它不能调用或要求存在复制/移动构造函数,这就是为什么您只能从int&
中看到构造函数):
以下是CPPFerence的一段引用(虽然不如标准,但足够接近):
语言规则确保不会发生复制/移动操作,
即使在概念上:
- 在初始化变量时,当初始值设定项表达式 是与相同类别类型(忽略cv限定)的prvalue 变量类型: tx=T(T(T());//只有一次调用T的默认构造函数来初始化x
谢谢你的解释。你能解释一下为什么Foo(2)返回一个整数吗?我知道它是一个匿名对象,但在其构造函数体中没有返回语句。@sangminpark Foo(2)不返回任何内容,只返回构造的Foo对象。Foo(2)使用
int&
构造Foo,外部复制/移动构造函数被省略。您可以编写Foo(Foo(Foo(Foo(2))),得到的唯一构造函数是Foo(2)。所有othet复制/移动构造函数都将被忽略。我不是语言律师,我不确定这是否是c++17为本案规定的,但编译器无论如何都会这么做。通过简单地删除copy和move构造函数并观察错误,很容易检查编译器是否认为这里强制执行了copy省略。我手头没有检查的标准,但我非常确定,即使一个副本将被省略,如果copy ctor声明为deleted,使用“引用已删除的函数”诊断代码将无法编译。@正如我所怀疑的,较新的clang和gcc保证在C++17模式下(尽管删除了复制ctor),但不能在C++14模式下进行这种复制省略。不确定标准是怎么说的根据cppreference,在C++17中,这些复制/移动构造函数保证被省略,并且不应该被要求存在。将此添加到答案中
Foo f = num; // custom constructor
Foo f4(Foo(2));