获取要使用的移动构造函数/赋值运算符

时间:2013-07-10 14:01:43

标签: c++ c++11 move-semantics rvalue-reference

请考虑以下代码:

#include <iostream>

#define P_(x) std::cout << x << std::endl

class B {
public:
    B() { P_("B::B()"); }
    B(const B&) { P_("B::B(const B&)"); }
    B(B&&) { P_("B::B(B&&)"); }
    ~B() { P_("B::~B()"); }

    B& operator=(const B&) { P_("B::op=(const B&)"); return *this; }
    B& operator=(B&& b) { P_("B::op=(B&&)"); return *this; }
};

class Foo {
public:
    void setB(const B& b) { mB = b; }
private:
    B mB;
};

B genB() {
    return B();
}

int main() {
    Foo f;
    f.setB(genB());
}

假设B是一种难以复制构造的类型。我想生成一些B(使用函数genB)并将其存储在Foo中。由于genB返回临时结果,我希望可以使用移动构造函数。

但是,当我运行代码时,我得到了这个输出:

B::B()
B::B()
B::op=(const B&)
B::~B()
B::~B()

这清楚地表明两个B被创建和销毁,但第二个是副本,而不是第一个。

尽可能使用移动构造函数的最佳方法是什么?

  • 我需要在某处调用std :: move()吗?
  • 我是否需要为B&B&&
  • 单独重载
  • 我还缺少其他的东西吗?

2 个答案:

答案 0 :(得分:3)

您可以重载setB函数:

class Foo {
public:
    void setB(const B& b) { mB = b; }
    void setB(B&& b) { mB = std::move(b); }
private:
    B mB;
};

或者,您可以使用“按值传递”方式:

class Foo {
public:
    void setB(B b) { mB = std::move(b); }
private:
    B mB;
};

此处,参数b将在可能时移动构造或以其他方式复制构造。

答案 1 :(得分:0)

第一个B实例是在创建Foo实例时创建的实例:

Foo f;

这是因为您的Foo班级有一个名为B的{​​{1}}成员。

第二个mB实例是B调用创建的实例。

由于您在genB()函数中执行的赋值:

,因此调用赋值运算符
Foo::setB

没有机会使用副本或移动构造函数。