如何解决在复制构造函数中做指针的深层复制向量,使两个向量成员都改变了?
我需要在我的项目中进行深度复制,现在我将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
成员绝对无效。
但是,即使删除了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));
}
}
您还需要根据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);
}
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。