关于std::vector 可能存在浅拷贝问题场景:
std::vector
是一个模板类,用于表示大小可变的数组。当你尝试拷贝或赋值一个 std::vector
时,实际上发生的是浅拷贝,即只拷贝了 vector
的元数据(如内存地址、大小和容量),而不是它包含的元素。如果 vector
包含指针或其他需要深度拷贝的对象,则在拷贝后和原始 vector
对象中的对象会指向同一个内存地址,这可能会导致问题,如违反对象唯一性原则、指针悬挂等。
解决方法:
为了解决浅拷贝的问题,你需要进行深拷贝。这可以通过以下几种方式实现:
-
手动拷贝每个元素:
std::vector<MyClass> v1;
// 填充 v1
std::vector<MyClass> v2;
for (const auto& elem : v1) {
v2.push_back(elem); // 对于支持拷贝构造的类型,这会进行深拷贝
}
2. 使用标准库函数 std::for_each
和 std::back_inserter
:
std::vector<MyClass> v1;
// 填充 v1
std::vector<MyClass> v2;
std::for_each(v1.begin(), v1.end(), [&](const MyClass& elem) {
v2.push_back(elem);
});
3. 利用 std::vector
的拷贝构造函数和 std::vector::assign
方法:
std::vector<MyClass> v1;
// 填充 v1
std::vector<MyClass> v2(v1.begin(), v1.end()); // 拷贝构造
// 或者
std::vector<MyClass> v2;
v2.assign(v1.begin(), v1.end()); // assign 方法
4. 如果 MyClass
有自己的拷贝构造函数进行深拷贝,可以直接使用 std::vector
的默认拷贝构造函数或者 operator=
进行深拷贝。
std::vector<MyClass> v1;
// 填充 v1
std::vector<MyClass> v2 = v1; // 拷贝构造
// 或者
std::vector<MyClass> v2;
v2 = v1; // 赋值操作
确保 MyClass
或其他存储在 vector
中的类型支持深拷贝,并且在拷贝构造函数、赋值运算符以及析构函数中正确处理内存。
定义std::vector 成员的结构体拷贝:
包含std::vector 的结构体直接赋值是可以的,不存在浅拷贝的问题。vector 调用赋值运算符时候,新的vector 会重新申请一块堆内存来存放元素数据,原来的vector 的堆内存释放或者修改不会对新的vector 有影响。
#include <iostream>
#include <algorithm>
#include <vector>
#include <array>
using namespace std;
struct DataInclueVector
{
unsigned int data0;
int data1;
std::vector<int> dataVec;
};
DataInclueVector g_dataIncludeVec{};
void printLog()
{
//printing vector
cout << "print vec data:" << endl;
for (int x : g_dataIncludeVec.dataVec)
cout << x << " ";
cout << endl;
}
void copyDataIncludeVec(DataInclueVector & dataVec)
{
g_dataIncludeVec = dataVec;
}
void initData()
{
DataInclueVector dataIncludeVec{1,2,{3,4}};
dataIncludeVec.dataVec.push_back(5);
copyDataIncludeVec(dataIncludeVec);
printLog();
dataIncludeVec.dataVec.erase(dataIncludeVec.dataVec.begin());
std::vector<int> ().swap(dataIncludeVec.dataVec);
}
int main()
{
initData();
printLog();
return 0;
}