为什么在元组初始化中构造的对象被复制了?

时间:2017-04-17 19:26:41

标签: c++ copy tuples move rvalue

我有一种情况无法绕过我的脑袋。我定义了一个不可复制的结构,并希望在元组中就地构造它。如果我这样做,它会被复制。我认为问题可能是std::make_tuple,但它不是。

如果我构造对象,然后在元组中移动它,事情按预期工作。

演示(我使用std::exit来阻止正常销毁的输出。)

#include <tuple>
#include <iostream>
#include <cstdlib>

struct MoveMe {
    MoveMe(size_t s) : size(s) {}
    MoveMe(MoveMe&&) = default;
    MoveMe(const MoveMe&) = delete;

    MoveMe& operator=(MoveMe&&) = default;
    MoveMe& operator=(const MoveMe&) = delete;

    ~MoveMe() {
        std::cout << "Destroyed" << std::endl;
    }

    size_t size = 0;
};

int main(int, char**) {
    std::cout << "Constructed in-place." << std::endl;
    auto tuple = std::make_tuple(MoveMe{10});

    std::cout << std::endl << "Other tests." << std::endl;
    std::tuple<MoveMe> tuple2 = std::tuple<MoveMe>(MoveMe{10});

    std::cout << std::endl << "Moved." << std::endl;
    MoveMe obj{10};
    auto tuple3 = std::make_tuple(std::move(obj));

    std::exit(0);
    // return 0;
}

输出

  

就地建造。

     

销毁

     

其他测试。

     

销毁

     

移动。

为什么会这样?我对rvalues的理解是基本的,所以我的猜测是我错过了一些明显的东西。谢谢。

1 个答案:

答案 0 :(得分:1)

未复制它仍然被移动。

在您的情况下,您正在创建一个临时(MoveMe{10}),然后用于在元组中移动构造MoveMe的实例。移动构造元组中MoveMe的实例后,移动的临时文件将被销毁。

您可以通过转发参数

直接在元组中构造MoveMe对象
std::cout << "Directly Constructed" << std::endl;
auto tuple = std::tuple<MoveMe>(10);

这不会导致临时创建然后被破坏。