【问题标题】:Why this move constructor is so greedy?为什么这个移动构造函数如此贪婪?
【发布时间】:2014-10-09 23:56:14
【问题描述】:

我有以下代码:

#include <iostream>

class foo_class {
    std::string value;
public:
    foo_class(const foo_class& v) : value{v.value} {
        std::cout << "copy constructor" << std::endl;
    }

    foo_class(foo_class&& v) : value{std::move(v.value)} {
        std::cout << "move constructor" << std::endl;
    }

    ~foo_class() {
        std::cout << "destructor" << std::endl;
    }

    foo_class(std::string v) : value{std::move(v)} {
        std::cout << "type constructor" << std::endl;
    }
};

struct Data {
    foo_class a;
    foo_class b;
};

int main() {
    std::string c = "3";
    Data x{c,c+"3"};
    return 0;
}

重要,我用 GCC 和 Clang(分别为 4.8.2 和 3.4)和标志 -fno-elide-constructors 编译它,所以我们不会省略复制/移动构造函数。

执行结果如下:

type constructor
move constructor
destructor
type constructor
move constructor
destructor
destructor
destructor

这意味着复制构造函数根本没有被使用,即使它应该用于 struct Data 的构造函数的第一个参数。

接下来,如果我删除复制构造函数,根据我的编译器,代码仍然是合法的,但在我的理解中应该是非法的,因为在传递第一个参数时我没有强制转换为 &&(使用 std::move) Data的构造函数。

我的问题很简单: 为什么会这样? 我错过了什么吗?

【问题讨论】:

  • 为什么你认为它应该是一个副本?两个参数都经过转换,所以你有两个可以移动的临时变量。
  • 是否意味着如果不在Data中声明转发构造函数就无法完美转发到std::string值?
  • “完美转发”是一个适用于模板函数的概念,你没有。您的代码将字符串的内容直接移动到x,这与一组完美的转发函数所做的事情是一样的。尽管您的类型构造函数中确实有一个额外的副本。

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


【解决方案1】:

因为foo_class对象构造在

Data x{c,c+"3"};

都是临时的。所以他们调用 move 构造函数而不是 copy 构造函数。

type constructor // 1. Construct a temporary foo_class object out of string "c" for a
move constructor // 2. Move the temporary object created above to x.a
destructor       // 3. Destruct the temporary foo_class object created in 1
type constructor // 4. Same as 1, but the object is for b, and the string "33"
move constructor // 5. Same as 2, moved to x.b
destructor       // 6. Destruct the temporary foo_class object created in 4
destructor       // 7. Destruct x.b
destructor       // 8. Destruct x.a

【讨论】:

    猜你喜欢
    • 2012-04-29
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 2015-01-12
    • 2013-04-25
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多