C++类成员std::map中的值丢失,如何确保数据持久保存?
问题分析与解决方案
这个问题我太熟了——你踩了C++对象拷贝的坑!咱们一步步拆解:
为什么数据会丢失?
看你的newReading方法:它创建了一个InuReading对象,把它push到readings vector里,然后返回的是这个对象的副本。之后你在addTemperatureReading里修改的是这个副本的data map,而vector里存储的原始对象根本没被改动!所以主函数里从vector取出对象时,data自然是空的。
三种解决办法,按需选:
1. 返回对象引用(最直接的修复)
修改newReading的返回类型为引用,这样返回的是vector里原始对象的引用,修改引用就等于直接改动vector里的对象:
首先修改InuTask的头文件声明:
class InuTask{ public: InuTask(String); String type; void addTemperatureReading(String sensor, float temperature); std::vector<InuReading> readings; private: // 把返回类型改成InuReading& InuReading& newReading(String t, String l); };
然后修改方法实现:
InuReading& InuTask::newReading(String t, String l){ // 用emplace_back直接在vector内部构造对象,避免额外拷贝 readings.emplace_back(t, l); // 返回vector最后一个元素的引用 return readings.back(); }
这样在addTemperatureReading里,r就是vector中对象的引用,调用r.set会直接修改原始对象,主函数里打印task.readings[0].data.size()就会得到1了。
2. 直接操作vector中的元素(简化逻辑)
如果不想用引用,也可以去掉newReading方法,直接在addTemperatureReading里构造并修改对象:
void InuTask::addTemperatureReading(String sensor, float temperature){ // 直接在vector里构造InuReading对象 readings.emplace_back("temperature", sensor); // 直接修改vector最后一个元素的data readings.back().set("d", temperature); }
这种方式更直接,也完全避免了拷贝问题。
3. 禁用拷贝构造(从根源防止踩坑)
如果想彻底避免这类“误改副本”的问题,可以禁用InuReading的拷贝构造和赋值运算符,让编译器帮你提前发现错误:
class InuReading{ public: InuReading(String t, String l){ type = t; label = l; }; // 禁用拷贝构造和赋值运算符 InuReading(const InuReading&) = delete; InuReading& operator=(const InuReading&) = delete; // 保留移动构造(如果需要转移对象所有权) InuReading(InuReading&&) = default; InuReading& operator=(InuReading&&) = default; String type; String label; std::map<String, String> data; void set(String key, float d); };
这样如果不小心写出返回副本或者拷贝对象的代码,编译器会直接报错,从根源避免这类问题。
内容的提问来源于stack exchange,提问作者user2145184
相关产品推荐
相关产品推荐

