删除struct成员后如何保留std::vector中存储的struct类型元素的值
问题根因
std::vector::push_back对未自定义拷贝逻辑的结构体执行默认浅拷贝,只会复制结构体内部的指针地址,不会复制指针指向的堆内存内容。你声明的变量a和存入vector的A实例的str指针指向同一块内存,释放a.str时这块内存会被回收,vector内的指针就变成了野指针,自然读取不到原有内容。
解决方法
要实现删除a.str后vector内的值仍然保留,核心是让vector内的A实例拥有独立的内存副本,和原变量a的指针不共用内存,有两种常用实现方案:
方案1:给结构体自定义深拷贝逻辑
符合C++三/五法则要求,手动实现拷贝构造、赋值运算符重载、析构函数,完成堆内存的独立复制与释放,示例代码如下:
#include <vector> #include <string> #include <cstring> struct A { char* str; char* str1; // 自定义拷贝构造,push_back时自动调用,为新实例申请独立内存 A(const A& other) { str = new char[strlen(other.str) + 1]; strcpy(str, other.str); str1 = new char[strlen(other.str1) + 1]; strcpy(str1, other.str1); } // 赋值运算符重载,避免赋值时出现浅拷贝 A& operator=(const A& other) { if (this == &other) return *this; // 先释放原有内存 delete[] str; delete[] str1; // 申请新内存复制内容 str = new char[strlen(other.str) + 1]; strcpy(str, other.str); str1 = new char[strlen(other.str1) + 1]; strcpy(str1, other.str1); return *this; } // 析构函数自动释放内存,避免泄漏 ~A() { delete[] str; delete[] str1; } }; int main(){ std::vector<A> vect; std::string b = "Data structures using c and c++"; A a; // 修正原代码内存申请错误:按字符串实际长度申请空间,避免越界 a.str = new char[b.size() + 1]; a.str1 = new char[16]; strcpy(a.str, b.c_str()); strcpy(a.str1, "test content"); vect.push_back(a); // 此时调用自定义拷贝构造,vector内元素有独立内存 // 释放a的内存,不会影响vector内的内容 delete[] a.str; delete[] a.str1; a.str = a.str1 = nullptr; // vector内的元素内容可正常访问 return 0; }
注意:
new[]申请的数组内存必须用delete[]释放,用delete属于未定义行为。
方案2:用std::string替换裸指针(更推荐)
std::string内部已经实现了安全的深拷贝逻辑,不需要手动管理内存,代码更简洁也更不容易出错,示例如下:
#include <vector> #include <string> struct A { std::string str; std::string str1; }; int main(){ std::vector<A> vect; std::string b = "Data structures using c and c++"; A a; a.str = b; a.str1 = "test content"; vect.push_back(a); // string自动完成深拷贝,vector内有独立副本 a.str.clear(); // 清空a的str,或者直接销毁a,都不会影响vector内的内容 return 0; }
额外注意事项
- 原代码中
new char[10*sizeof(char*)]写法错误:sizeof(char*)是指针本身的大小(64位系统下为8字节),存储字符串只需按字符数申请内存即可,该写法会导致内存申请冗余甚至后续字符串越界。 - 手动管理裸指针内存极易出现泄漏、野指针、越界问题,非必要场景优先用STL容器代替裸指针。
内容的提问来源于stack exchange,提问作者somu_mtech
相关产品推荐
相关产品推荐

