在复制构造函数中做指针的深度复制向量是否改变了两个向量成员?
doing deep copy vector of pointers in copy constructor got both vector member changed?
我需要在我的项目中进行深层复制,现在我 memcpy
将 srcObj
转换为 destObj
然后
如果 destObj
拥有指针成员,我只需创建所有 obj 并递归执行此方法
这是伪造的:
class B
{
public:
B(int id_) : id(id_) {};
int id = 0;
};
class A
{
public:
vector<B*> vecInt;
B objB = 111;
A()
{
vecInt.push_back(new B(1));
vecInt.push_back(new B(2));
vecInt.push_back(new B(3));
}
A(const A& rhs)
{
memcpy(this, &rhs, sizeof(A));
for (auto i = 0; i < rhs.vecInt.size(); i++)
{
auto ptrTmp = new B(rhs.vecInt[i]->id);
cout << "00000000000 " << rhs.vecInt[i] << endl;;
this->vecInt[i] = ptrTmp;
cout << "11111111111 " << ptrTmp << endl;;
cout << "22222222222 " << rhs.vecInt[i] << endl;;
}
}
};
这是问题所在,每次我在循环中分配 this->vecInt[i]
时,rhs.vecInt[i]
也会发生变化,它们都指向一个地址,我不知道为什么会这样。
感谢任何帮助。
memcpy()
绝对错误,需要删除。它正在破坏你的 A
对象的数据成员。它可能 对 objB
成员有效,但绝对不适用于 vecInt
成员。
但是,即使删除了 thae memcpy()
,您仍然会有 未定义的行为,因为您试图分配给 vector
未定义的元素还存在。对于 deep-copy 指针向量,您别无选择,只能一次克隆每个动态 B
对象并将其添加到新的 vector
.
实现复制构造函数的正确方法应该更像这样:
A(const A& rhs) : objB(rhs.objB)
{
vecInt.reserve(rhs.vecInt.size());
for (auto *elem : rhs.vecInt)
{
vecInt.push_back(new B(*elem));
}
}
根据 Rule of 3/5/0:
,您还需要添加析构函数、移动构造函数、复制赋值运算符和移动赋值运算符
class A
{
public:
vector<B*> vecInt;
B objB = 111;
A()
{
vecInt.push_back(new B(1));
vecInt.push_back(new B(2));
vecInt.push_back(new B(3));
}
A(const A& rhs) : objB(rhs.objB)
{
vecInt.reserve(rhs.vecInt.size());
for (auto *elem : rhs.vecInt)
{
vecInt.push_back(new B(*elem));
}
}
A(A&& rhs) : vecInt(move(rhs.vecInt)), objB(move(rhs.objB)) {}
~A()
{
for(auto *elem : vecInt)
delete elem;
}
A& operator=(A rhs)
{
vecInt.swap(rhs.vecInt);
objB.id = rhs.objB.id;
return *this;
}
};
也就是说,考虑使用 std::vector<std::unique_ptr<B>>
而不是 std::vector<B*>
。这将消除对显式析构函数的需要。如果可以避免,请不要在现代 C++ 中使用 new
/delete
。
class A
{
public:
vector<unique_ptr<B>> vecInt;
B objB = 111;
A()
{
vecInt.push_back(make_unique<B>(1));
vecInt.push_back(make_unique<B>(2));
vecInt.push_back(make_unique<B>(3));
}
A(const A& rhs) : objB(rhs.objB)
{
vecInt.reserve(rhs.vecInt.size());
for (auto &elem : rhs.vecInt)
{
vecInt.push_back(make_unique<B>(*elem));
}
}
A(A&& rhs) : vecInt(move(rhs.vecInt)), objB(move(rhs.objB)) {}
~A() = default;
A& operator=(A rhs)
{
vecInt.swap(rhs.vecInt);
objB.id = rhs.objB.id;
return *this;
}
};
更好的是,只需使用 std::vector<B>
,让编译器为您处理其他一切:
class A
{
public:
vector<B> vecInt;
B objB = 111;
A()
{
vecInt.emplace_back(1);
vecInt.emplace_back(2);
vecInt.emplace_back(3);
}
};
我需要在我的项目中进行深层复制,现在我 memcpy
将 srcObj
转换为 destObj
然后
如果 destObj
拥有指针成员,我只需创建所有 obj 并递归执行此方法
这是伪造的:
class B
{
public:
B(int id_) : id(id_) {};
int id = 0;
};
class A
{
public:
vector<B*> vecInt;
B objB = 111;
A()
{
vecInt.push_back(new B(1));
vecInt.push_back(new B(2));
vecInt.push_back(new B(3));
}
A(const A& rhs)
{
memcpy(this, &rhs, sizeof(A));
for (auto i = 0; i < rhs.vecInt.size(); i++)
{
auto ptrTmp = new B(rhs.vecInt[i]->id);
cout << "00000000000 " << rhs.vecInt[i] << endl;;
this->vecInt[i] = ptrTmp;
cout << "11111111111 " << ptrTmp << endl;;
cout << "22222222222 " << rhs.vecInt[i] << endl;;
}
}
};
这是问题所在,每次我在循环中分配 this->vecInt[i]
时,rhs.vecInt[i]
也会发生变化,它们都指向一个地址,我不知道为什么会这样。
感谢任何帮助。
memcpy()
绝对错误,需要删除。它正在破坏你的 A
对象的数据成员。它可能 对 objB
成员有效,但绝对不适用于 vecInt
成员。
但是,即使删除了 thae memcpy()
,您仍然会有 未定义的行为,因为您试图分配给 vector
未定义的元素还存在。对于 deep-copy 指针向量,您别无选择,只能一次克隆每个动态 B
对象并将其添加到新的 vector
.
实现复制构造函数的正确方法应该更像这样:
A(const A& rhs) : objB(rhs.objB)
{
vecInt.reserve(rhs.vecInt.size());
for (auto *elem : rhs.vecInt)
{
vecInt.push_back(new B(*elem));
}
}
根据 Rule of 3/5/0:
,您还需要添加析构函数、移动构造函数、复制赋值运算符和移动赋值运算符class A
{
public:
vector<B*> vecInt;
B objB = 111;
A()
{
vecInt.push_back(new B(1));
vecInt.push_back(new B(2));
vecInt.push_back(new B(3));
}
A(const A& rhs) : objB(rhs.objB)
{
vecInt.reserve(rhs.vecInt.size());
for (auto *elem : rhs.vecInt)
{
vecInt.push_back(new B(*elem));
}
}
A(A&& rhs) : vecInt(move(rhs.vecInt)), objB(move(rhs.objB)) {}
~A()
{
for(auto *elem : vecInt)
delete elem;
}
A& operator=(A rhs)
{
vecInt.swap(rhs.vecInt);
objB.id = rhs.objB.id;
return *this;
}
};
也就是说,考虑使用 std::vector<std::unique_ptr<B>>
而不是 std::vector<B*>
。这将消除对显式析构函数的需要。如果可以避免,请不要在现代 C++ 中使用 new
/delete
。
class A
{
public:
vector<unique_ptr<B>> vecInt;
B objB = 111;
A()
{
vecInt.push_back(make_unique<B>(1));
vecInt.push_back(make_unique<B>(2));
vecInt.push_back(make_unique<B>(3));
}
A(const A& rhs) : objB(rhs.objB)
{
vecInt.reserve(rhs.vecInt.size());
for (auto &elem : rhs.vecInt)
{
vecInt.push_back(make_unique<B>(*elem));
}
}
A(A&& rhs) : vecInt(move(rhs.vecInt)), objB(move(rhs.objB)) {}
~A() = default;
A& operator=(A rhs)
{
vecInt.swap(rhs.vecInt);
objB.id = rhs.objB.id;
return *this;
}
};
更好的是,只需使用 std::vector<B>
,让编译器为您处理其他一切:
class A
{
public:
vector<B> vecInt;
B objB = 111;
A()
{
vecInt.emplace_back(1);
vecInt.emplace_back(2);
vecInt.emplace_back(3);
}
};