首页 > 解决方案 > 为什么不调用移动构造函数

问题描述

所以我是移动语义的新手,我正在测试以下代码。我的理解是右值将调用移动构造函数,我预计 A("123") 将导致调用移动构造函数。但是当我运行它时,会调用复制构造函数。

#include <string>
#include <iostream>
#include <utility>

class  A
{
    std::string s;
    public:

    A(const std::string& in) : s(in) { std::cout << "ctor!\n";}
    A(const A& o) : s(o.s) { std::cout << "move failed!\n"; }
    A(A&& o) noexcept : s(std::move(o.s)) { }
};

class  B
{
    A d_a;
    public:
    B(const A& a) :d_a(a)
{}
};

int main()
{
    std::cout << "Trying to move A\n";
    B b(A("123")); // move-constructs from rvalue temporary

}

标签: c++

解决方案


问题是构造函数B

B(const A& a) :d_a(a) {}

函数参数const A&是一个 const 限定的左值引用,您不能将其强制转换为右值。您需要将构造函数更改为(或添加第二个)

B(A&& a) : d_a(std::move(a)) {}

作为旁注,您可以免费获得示例中类型的正确移动语义,如果您将它们定义为

struct  A {
    std::string s;
};

struct B {
     A d_a;
};

与客户端代码

B b{A{"123"}};

我知道您不想依赖编译器生成的特殊成员函数来研究移动构造,我只是不想省略这个快捷方式,因为这是一个应该努力的设置:让复制和你的类的移动语义由它们的数据成员自动组装。


推荐阅读