动态替换动态分配数组内容失效,为何出现错误输出?
动态数组复制后vector元素异常的原因
问题代码
struct A { int *p; }; int main() { vector<A> v; A test; test.p = new int[5]; //fill the array for (int i = 0; i < 5; i++) test.p[i] = i; v.push_back(test); A test2; test2.p = new int[10]; //fill the array for (int i = 0; i < 10; i++) test2.p[i] = i; delete[] test.p; //reallocate test to test2 test.p = new int[10]; //copy test2 to test for (int i = 0; i < 10; i++) test.p[i] = test2.p[i]; //delete test2 delete[] test2.p; //print the array for (int i = 0; i < 10; i++) cout << v[0].p[i] << endl; return 0; }
异常输出
0 0 -997294064 32767 4 0 33 0 -997220688 32767
问题根源
核心问题是浅拷贝导致的野指针访问:
- 当执行
v.push_back(test);时,vector会复制一份test对象存入容器。但struct A的默认拷贝构造函数只会复制指针p的数值,不会复制指针指向的内存——也就是说,容器里的A对象和原test对象的p指针指向同一块int[5]的内存。 - 后续调用
delete[] test.p;直接释放了这块内存,此时v[0].p就变成了野指针,指向已经被系统回收的内存空间。 - 最后访问
v[0].p[i]属于访问已释放的内存,这是C++中的未定义行为,因此输出出现随机乱码。
你后续给test的p重新分配新内存的操作,和容器里的v[0].p没有任何关联,容器内的指针依然指向已释放的旧内存。
解决办法
1. 实现深拷贝
给struct A定义自定义的拷贝构造函数、赋值运算符和析构函数,在拷贝时复制指针指向的内存,而非仅复制指针本身:
struct A { int size; int *p; // 构造函数 A(int s = 0) : size(s), p(s ? new int[s] : nullptr) {} // 拷贝构造函数 A(const A& other) : size(other.size), p(new int[other.size]) { for (int i = 0; i < size; i++) { p[i] = other.p[i]; } } // 赋值运算符重载 A& operator=(const A& other) { if (this != &other) { delete[] p; size = other.size; p = new int[size]; for (int i = 0; i < size; i++) { p[i] = other.p[i]; } } return *this; } // 析构函数 ~A() { delete[] p; } };
2. 避免手动管理内存
直接用std::vector<int>替代int*,让标准库自动处理内存和拷贝逻辑,代码更简洁安全:
struct A { vector<int> p; }; int main() { vector<A> v; A test; test.p.resize(5); for (int i = 0; i < 5; i++) test.p[i] = i; v.push_back(test); A test2; test2.p.resize(10); for (int i = 0; i < 10; i++) test2.p[i] = i; test.p = test2.p; // vector自动完成深拷贝 for (int i = 0; i < 5; i++) cout << v[0].p[i] << endl; return 0; }
内容的提问来源于stack exchange,提问作者Carlos López Martínez
相关产品推荐
相关产品推荐

