提问人:liiight 提问时间:10/29/2020 更新时间:10/29/2020 访问量:296
在复制构造函数中做指针的深度复制向量是否更改了两个向量成员?
doing deep copy vector of pointers in copy constructor got both vector member changed?
问:
我需要在我的项目中进行深度复制,现在我进入了
如果拥有指针成员,我只需创建所有 obj 并以递归方式执行此方法memcpy
srcObj
destObj
destObj
这是伪:
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]
感谢任何帮助。
答:
1赞
Remy Lebeau
10/29/2020
#1
这是绝对错误的,需要删除。它正在损坏对象的数据成员。它可能对会员有用,但绝对对会员无效。memcpy()
A
objB
vecInt
但是,即使删除了 thae,在尝试分配给尚不存在的元素时,您仍然会有未定义的行为。若要深度复制指针向量,您别无选择,只能一次克隆一个动态对象并将其添加到新的 .memcpy()
vector
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));
}
}
您还需要根据 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;
}
};
话虽如此,请考虑使用 代替 .这将消除对显式析构函数的需求。如果可以避免,请不要在现代 C++ 中使用 /。std::vector<std::unique_ptr<B>>
std::vector<B*>
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);
}
};
评论
0赞
liiight
10/29/2020
感谢您的帮助,我还没有注意到它是如此恶毒,它现在可以工作了,但是由于我需要为某些对象使用太多指针,我想我只是无法实现最后一个。但是既然现在不能使用,那么我应该一个接一个地分配所有数据成员,我只是觉得这真的很难维护,还是有其他方法可以处理这么多数据成员的情况?memcpy
memcpy
评论
memcpy
memcpy