与移动构造函数混淆:无法调用移动构造函数

时间:2017-06-02 14:15:29

标签: c++ move-semantics rvalue-reference move-constructor most-vexing-parse

我在使用C ++理解移动构造函数时遇到了困难。我用默认构造函数,复制构造函数,移动构造函数和析构函数创建了一个简单的类。此外,我已经定义了一个具有两个重载的函数,一个接受对该类的引用,另一个接受对该类的rvalue引用。我的测试代码如下。

#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

2 个答案:

答案 0 :(得分:9)

你没有看到第3行的任何输出的原因是它声明了一个函数,而不是一个变量。这是由于名为Most Vexing Parse的歧义。

set test2 = Doc.getElementById("testid") c s3(c())进行比较,由于隐式类型调整,与int foo(int ())相同。

为了解决这个问题,请使用大括号初始化(实际上在C ++ 11中引入了部分原因):

int foo(int (*f)())

答案 1 :(得分:5)

c s3(c());不构造任何对象。这是一个功能声明。该函数名为s3,返回类型为c,参数类型为&#34;指向函数的指针,不带参数并返回c&#34;。因此,您没有输出,因为函数声明不会调用任何函数。

为了避免这种情况,您可以使用列表初始化,c s3{c()};可能更符合您的想法。