需要一些帮助来理解C++;11移动构造函数 作为一个C++新手,我确实理解C++ 11的新的移动构造函数有问题,我希望有人能解释一下我遇到的一个具体的情况。让我们以下面的示例代码为例: #include <iostream> using namespace std; class Model { public: int data; Model(int data) : data(data) { cout << "Constructor" << endl; } Model(Model&& model) { cout << "Move constructor" << endl; } ~Model() { cout << "Destructor" << endl; } private: Model(const Model& model); const Model& operator=(const Model&); }; Model createModel(int data) { return Model(data); } int main(void) { Model model = createModel(1); cout << model.data << endl; return 0; }

需要一些帮助来理解C++;11移动构造函数 作为一个C++新手,我确实理解C++ 11的新的移动构造函数有问题,我希望有人能解释一下我遇到的一个具体的情况。让我们以下面的示例代码为例: #include <iostream> using namespace std; class Model { public: int data; Model(int data) : data(data) { cout << "Constructor" << endl; } Model(Model&& model) { cout << "Move constructor" << endl; } ~Model() { cout << "Destructor" << endl; } private: Model(const Model& model); const Model& operator=(const Model&); }; Model createModel(int data) { return Model(data); } int main(void) { Model model = createModel(1); cout << model.data << endl; return 0; },c++,c++11,move-semantics,C++,C++11,Move Semantics,因此,从未调用Move构造函数。我不明白为什么我必须指定move构造函数才能在运行时完全不使用它的情况下编译程序 是因为编译器(GCC4.8.2)优化了移动构造函数吗?或者这里还有其他的魔术表演吗 有人能解释一下上面的代码到底发生了什么吗?代码实现了我想要的功能,但我真的不明白为什么。我认为这就是您所说的复制省略(即阻止对象的复制)并直接使用它。请参阅:您是这里的“受害者” 注意:“C++中,允许改变所得到的程序的可观察行为特别值得注意。” 编辑:因此,允许编译器应用优化,即使移动向量(cout

因此,从未调用Move构造函数。我不明白为什么我必须指定move构造函数才能在运行时完全不使用它的情况下编译程序

是因为编译器(GCC4.8.2)优化了移动构造函数吗?或者这里还有其他的魔术表演吗


有人能解释一下上面的代码到底发生了什么吗?代码实现了我想要的功能,但我真的不明白为什么。

我认为这就是您所说的复制省略(即阻止对象的复制)并直接使用它。请参阅:

您是这里的“受害者”

注意:“C++中,允许改变所得到的程序的可观察行为特别值得注意。”


编辑:因此,允许编译器应用优化,即使移动向量(cout)的副作用已更改。

程序中可能会发生两种移动:

  • 从函数到返回对象
  • 从返回对象到
    模型
  • 出于相同的原因,编译器可以省略这两种移动:

    当未绑定到引用(12.2)的临时类对象将被复制/移动到具有相同cv类型的类对象时,可以通过将临时对象直接构造到省略的复制/移动的目标中来省略复制/移动操作

    还存在发生复制/移动省略的其他情况(参见C++11中的§12.8/31)。请注意,复制/移动省略是完全可选的-编译器不必这样做

    请注意,只要不改变程序的行为,编译器就可以对任何内容进行绝对优化。标准中明确提到复制/移动省略的原因是,如果复制/移动构造函数有副作用,它可能会改变程序的行为。允许编译器执行此优化,即使它更改了程序的行为。这就是为什么复制/移动构造函数永远不会有副作用的原因,因为这样您的程序将有多个有效的执行路径


    您可以将
    -fno-elide构造函数
    选项传递到
    gcc
    ,以确保永远不会执行此优化。

    搜索“返回值优化”(RVO),这已经被谈论了很多(包括这里)。由于在链接中
    返回a
    语句调用
    move
    构造函数,这里不是这种情况,这就是OP提出问题的原因。在使用
    -fno-elide构造函数
    选项编译代码后,我终于能够看到移动构造函数的效果,也能够使用移动赋值操作符,我想我现在终于理解了C++11的移动语义。谢谢!
    
    Constructor
    1
    Destructor