从 std::list 中 std::move 元素后获得无效输出

Har*_*rry 1 c++ stdlist stdmove

我试图了解 std::move 。在我的代码中,我正在从内部包含两个字段的std::list<struct Data>位置移动一个元素,但我没有得到预期的输出。这是我的代码:struct Datastd::string

#include <iostream>
#include <string>
#include <list>

struct Data {
    std::string topic {};
    std::string msg {};

    Data(const std::string& topic, const std::string& msg) {
        this->topic = topic;
        this->msg = msg;
    }
};

int main() {
    std::list<Data> data_list;
    data_list.push_back(Data("A", std::string(1000, 'a')));
    data_list.push_back(Data("B", std::string(1000, 'b')));
    data_list.push_back(Data("C", std::string(1000, 'c')));
    data_list.push_back(Data("D", std::string(1000, 'd')));
    data_list.push_back(Data("E", std::string(1000, 'e')));
    
    while (!data_list.empty()) {
        std::cout << (void*)&data_list.front() << "\n";
        Data&& d1 = std::move(data_list.front());
        data_list.pop_front();
        std::cout << d1.topic << ", " << d1.msg << "\n";
        std::cout << (void*)&d1 << "\n\n";
    }
    std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 6

这里的问题是你实际上并没有移动任何东西。当你调用时std::move,实际上没有任何东西被移动。它的作用是将您拥有的左值转换为右值,以便可以对其进行移动构造或移动分配。但这不是你在这里所做的。你用

Data&& d1 = std::move(data_list.front());
Run Code Online (Sandbox Code Playgroud)

它具有d1右值引用,意味着不再移动,它只是对列表中对象的引用。当您弹出该元素时,您的引用现在引用了一个不再存在的对象,并且使用它具有未定义的行为,导致您看到的输出。如果你想移动元素,你需要

Data d1 = std::move(data_list.front());
Run Code Online (Sandbox Code Playgroud)

现在d1将使用Data的隐式移动构造函数将列表元素移动到d1.

  • @Harry不,它将`data_list.front()`移动到`d1`。您的数据已经做到了。`std::string` 是一个类类型。它也有一个移动构造函数。既然如此,编译器生成的“Data”移动构造函数也会调用字符串的移动构造函数。这可能会为您解决问题:/sf/ask/217427731/ (2认同)