【问题标题】:Move semantics in C++11C++11 中的移动语义
【发布时间】:2019-01-02 11:42:21
【问题描述】:

我想完全理解 C++11 中的移动语义。所以我写了几个类来看看什么时候调用不同的构造函数:

#include <iostream>
using namespace std;

class A {
public:
    A() : a1_(0) {std::cout << "Calling constructor" << std::endl;}
    A(A&& other) {
        std::cout << "Calling move constructor" << std::endl;
        a1_ = other.a1_;
        other.a1_ = 0;
    }

    // Move assignment operator.
    A& operator=(A&& other) {
        std::cout << "Calling move operator" << std::endl;
        if (this != &other) {
            a1_ = other.a1_;
            other.a1_ = 0;
        }
        return *this;
    }

    // Copy constructor.
    A(const A& other) {
        std::cout << "Calling copy constructor" << std::endl;
        a1_ = other.a1_;
    }

    // Copy assignment operator.
    A& operator=(const A& other) {
        std::cout << "Calling copy assignment operator" << std::endl;
        if (this != &other) {
            a1_ = other.a1_;
        }
        return *this;
    }

private:
    int a1_;
};

class B {
    A oA_;

public:
    B() {}
    void setoA(A a) {oA_ = a;}
        A getoA() {return oA_;}
};

A createA() {
    A a1;
    return a1;
}

B createB() {
    B tmpB;
    A tmpA;
    tmpB.setoA(tmpA);
    return tmpB;
}

int main() {
    B b;
    A a;
    b.setoA(a);
    std::cout << "**************************" << std::endl;
    b.setoA(createA());
    std::cout << "**************************" << std::endl;
    b.setoA(std::move(createA()));
    std::cout << "**************************" << std::endl;
    B b2;
    b2.setoA(b.getoA());
    std::cout << "**************************" << std::endl;
    createB();

    return 0;
}

当我检查这段代码的输出时:

调用构造函数 调用构造函数 调用复制构造函数 调用复制赋值运算符 ++++++++++++++++++++++++++++++++++++++ 调用构造函数 调用复制赋值运算符 ++++++++++++++++++++++++++++++++++++++ 调用构造函数 调用移动构造函数 调用复制赋值运算符 ++++++++++++++++++++++++++++++++++++++ 调用构造函数 调用复制构造函数 调用复制赋值运算符 ++++++++++++++++++++++++++++++++++++++ 调用构造函数 调用构造函数 调用复制构造函数 调用复制赋值运算符

我有一些疑问:

我以为如果你传递r-value,就会调用move构造函数,是吗?这不是b.setoA(createA());r-value吗?

如何调用移动构造函数/操作符?

【问题讨论】:

  • 输出不是来自你的sn-p,请修复它。
  • abA 正在第一段中构建。您预计会有多少次施工电话?
  • 如果您对第一部分有疑问,请删除不相关的代码和输出,即创建minimal reproducible example
  • 复制省略是一回事。
  • 你的课上的货物太多了。删除不相关的代码。与移动语义无关。

标签: c++ c++11 operators move-semantics move-constructor


【解决方案1】:

首先在第一部分,为什么构造函数被调用两次?

因为您同时构造了 BA,而前者有自己的 A 实例,第一个(意外的)构造函数调用来自该实例。

我以为如果你传递 r-value move 构造函数会被调用,对吗?这不是b.setoA(createA()); r 值吗?

构造函数是从createA内部调用的(是的,返回值一个r值),但是会发生复制省略,对象直接在@987654326的参数变量中实例化@。

但是,在setoA 中,选择了复制分配,因为现在a 是一个左值。如果你想搬家,你需要:

void setoA(A a) { oA_ = std::move(a); }

【讨论】:

    【解决方案2】:

    编译器可以选择性地省略一些复制和移动。为防止这种情况,请在 GCC 和 Clang 中使用 -fno-elide-constructors。此外,一些移动省略在 C++17 中成为强制要求,因此要强制编译器使用 C++11 移动语义,请同时使用 -std=c++11

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-16
      • 2014-03-18
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      相关资源
      最近更新 更多