C++创建类实例数组时所有元素均为最新接收值的问题咨询
问题根因分析
你的代码核心问题是字符串仅存储了指针地址,没有拷贝实际内容,其次还有类成员缺失、浅拷贝的问题,具体如下:
- JSON解析返回的
char*指针通常指向JSON库内部的复用缓冲区:每次收到新的WebSocket消息解析JSON时,这个缓冲区会被新的报文内容覆盖。你所有Device实例的uid、name成员都指向同一个缓冲区地址,自然会随着新数据解析被同步修改。 - 你的
Device类定义遗漏了sensorType成员变量,当前代码无法正常编译,需要先补充声明。 - 你没有自定义类的拷贝构造函数、拷贝赋值运算符,默认生成的函数只会做浅拷贝,仅复制指针地址不会拷贝字符串内容,进一步放大了指针引用同一块内存的问题。
- 存在内存泄漏/野指针风险:如果后续缓冲区被释放,所有
Device实例的uid、name都会变成野指针,访问会直接崩溃。
修复方案
最简单可靠的方案是把类内的字符串成员替换为自动管理内存、支持深拷贝的字符串类:
如果是标准C++环境用std::string,如果是Arduino开发环境用String,修改后的类定义如下:
class Device { private: std::string uid; // Arduino环境替换为 String uid; std::string name; // Arduino环境替换为 String name; SensorType sensorType; // 补充缺失的成员变量 public: Device() = default; Device(const char* uid, const char* name, SensorType sensorType) : uid(uid), name(name), sensorType(sensorType) {} void Print() { Serial.print(uid.c_str()); // Arduino环境直接写 Serial.print(uid); Serial.print(" "); Serial.print(name.c_str()); // Arduino环境直接写 Serial.print(name); Serial.print(" "); Serial.print(sensorType); Serial.println(); } };
如果必须坚持用char*,则需要手动实现深拷贝逻辑,遵守三五法则:
class Device { private: char* uid = nullptr; char* name = nullptr; SensorType sensorType; public: Device() = default; Device(const char* uid, const char* name, SensorType sensorType) : sensorType(sensorType) { if(uid) { this->uid = (char*)malloc(strlen(uid)+1); strcpy(this->uid, uid); } if(name) { this->name = (char*)malloc(strlen(name)+1); strcpy(this->name, name); } } // 拷贝构造函数 Device(const Device& other) : sensorType(other.sensorType) { if(other.uid) { uid = (char*)malloc(strlen(other.uid)+1); strcpy(uid, other.uid); } if(other.name) { name = (char*)malloc(strlen(other.name)+1); strcpy(name, other.name); } } // 拷贝赋值运算符 Device& operator=(const Device& other) { if(this == &other) return *this; // 释放原有内存 free(uid); free(name); uid = nullptr; name = nullptr; sensorType = other.sensorType; // 拷贝新内容 if(other.uid) { uid = (char*)malloc(strlen(other.uid)+1); strcpy(uid, other.uid); } if(other.name) { name = (char*)malloc(strlen(other.name)+1); strcpy(name, other.name); } return *this; } // 析构函数释放内存 ~Device() { free(uid); free(name); } void Print() { Serial.print(uid); Serial.print(" "); Serial.print(name); Serial.print(" "); Serial.print(sensorType); Serial.println(); } };
内容的提问来源于stack exchange,提问作者OrElse
相关产品推荐
相关产品推荐

