Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 移动构造函数和右值引用_C++_Constructor_Move Semantics - Fatal编程技术网

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));