Den*_*niz 4 c++ rvalue-reference most-vexing-parse move-constructor move-semantics
我在使用C++理解移动构造函数时遇到了困难.我用默认构造函数,复制构造函数,移动构造函数和析构函数创建了一个简单的类.此外,我已经定义了一个具有两个重载的函数,一个接受对该类的引用,另一个接受对该类的右值引用.我的测试代码如下.
#include <iostream>
class c {
public:
    c() {
        std::cout << "default constructor" << std::endl;
    }
    c(const c& s) {
        std::cout << "copy constructor" << std::endl;
    }
    c(c&& s) {
        std::cout << "move constructor" << std::endl;
    }
    ~c() {
        std::cout << "destructor" << std::endl;
    }
};
void f(c& s) {
    std::cout << "passed by reference" << std::endl;
}
void f(c&& s) {
    std::cout << "passed by rvalue reference" << std::endl;
}
int main() {
    c s1; // line 1
    std::cout << "\n";
    c s2(s1); // line 2
    std::cout << "\n";
    c s3(c()); // line 3
    std::cout << "\n";
    f(s1); // line 4
    std::cout << "\n";
    f(c()); // line 5
    getchar();
    return 0;
}
我得到的输出并不是我所期待的.以下是我从此代码中获得的输出.
default constructor
copy constructor
passed by reference
default constructor
passed by rvalue reference
destructor
我可以理解所有行的输出除外line 3.上line 3,这是c s3(c());,c()是一个右值,所以我会想到s3会被举动构成.但输出并未表明它是移动构造的.在line 5,我正在做同样的事情并传递rvalue给函数f(),它确实调用接受rvalue引用的重载.我很困惑,并希望了解有关此事的任何信息.
编辑:如果我这样做,我可以调用移动构造函数c s3(std::move(c()));但是我还没有将rvalue传递给s3吗?我为什么需要std::move?
您没有看到第3行的任何输出的原因是它声明了一个函数,而不是一个变量.这是由于一种叫做Most Vexing Parse的歧义.
c s3(c())与之比较int foo(int ()),由于隐式类型调整,与...相同int foo(int (*f)()).
为了解决这个问题,请使用大括号初始化(部分由于这个原因,它实际上是在C++ 11中引入的):
c s3(c{});
// or
c s3{c()};
// or
c s3{c{}};
c s3(c());不构造任何对象.这是一个功能声明.调用该函数s3,返回类型为c,并且参数类型为"指向不带参数且返回的函数的指针c".因此,您没有输出,因为函数声明不会调用任何函数.
为了避免这种事情你可以使用列表初始化,   c s3{c()};可能更符合你的想法.