使用std::move移动std::list元素后得到无效输出的问题求解
问题原因分析
你代码的核心问题出在移动操作的实现逻辑有误,具体有两处错误:
- 没有实际触发移动构造:
std::move()本身仅负责将左值转换为右值引用类型,不会主动执行移动逻辑。你用Data&& d1右值引用接收返回值,本质是给std::list中存储的原元素起了个别名,没有生成新的Data对象,元素内容依然存放在list的内存空间中。 - 产生悬垂引用:后续调用
pop_front()时,list会直接销毁队首的原元素,此时d1引用指向的是已经被回收的内存,后续访问d1.topic、d1.msg属于未定义行为,自然无法得到预期输出。
修复方案
仅需要修改移动逻辑的接收类型,改为值接收即可真正触发移动构造:
#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的移动构造 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; }
逻辑说明
- 改为
Data d1 = std::move(data_list.front());后,会调用Data类隐式生成的移动构造函数,将原list元素中两个std::string的内部数据指针直接转移到局部变量d1中,没有大块内存拷贝,符合移动操作的性能预期。 - 后续执行
pop_front()销毁的是已经被移动后的空壳对象,不会影响d1的正常访问。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

