当涉及到类对象的指针向量时,我遇到了编写规则三的问题。搜索和示例似乎并不适用。我有这三个类:
class Data
{
private:
map<string, double> m_DataVariables;
public:
Data();
Data(const Data &data);
};
class Sample
{
private:
Data *m_pData;
public:
virtual ~Sample()
{
delete m_pData;
}
Sample();
Sample(const Sample &sample);
};
class BuildTree
{
private:
vector<Sample*> BuildSamples;
public:
BuildTree(vector<Sample*> &Samples);
// This does not compile
BuildTree(const BuildTree& other) : BuildSamples(new(other.BuildSamples))
{
}
~TreeBuilding()
{
for (int i = 0; i < BuildSamples.size(); ++i)
delete BuildSamples[i];
}
void BuildTrees(void);
};
1-不确定我是否正确删除了BuildSamples。
2-在构造函数中,希望将传递的参数的深层副本复制到成员变量BuildSamples中。
BuildTree::BuildTree(vector<Sample*> &samples)
{
BuildSamples = samples; // This just copies the references
}
如何编写复制构造函数以进行深层复制?我在这里缺少什么?
3-请注意:无法访问智能指针,share_ptr或unique_ptr等.C ++ 98就是我所拥有的。 请显示执行此操作所需的步骤。非常感谢您的时间和考虑。
答案 0 :(得分:1)
您可能需要以下内容:
BuildTree(const BuildTree& other)
{
BuildSamples.reserve(other.BuildSamples.size());
for (std::size_t i = 0; i != other.BuildSamples.size(); ++i) {
BuildSamples.push_back(new Sample(*other.BuildSamples[i]));
}
}
BuildTree(const vector<Sample*> &samples)
{
BuildSamples.reserve(samples.size());
for (std::size_t i = 0; i != samples.size(); ++i) {
BuildSamples.push_back(new Sample(*samples[i]));
}
}
答案 1 :(得分:1)
我注意到您将问题标记为c++98;即使C ++ 98不支持std::
中的智能指针,你当然可以使用Boost中定义的智能指针,例如: boost::shared_ptr
。
例如,代替使用vector<Sample*>
中的原始拥有指针,您可以使代码更简单
vector<boost::shared_ptr<Sample>>
。
通过这种方式,复制和销毁操作将在引擎盖下自动实现
。答案 2 :(得分:0)
您需要将BuildSamples
成员初始化为指针向量,并确保每个指针都指向传递的对象的克隆。一种方法是
BuildTree(const BuildTree& other) : BuildSamples(other.BuildSamples)
{
std::vector<Sample *>::iterator i = BuildSamples.begin(), end = BuildSamples.end();
while (i != end)
{
*i = new Sample(**i);
++i;
}
}
使用BuildSamples(other.BuildSamples)
初始化BuildSamples
并使用正确数量的元素,但这些元素与other.BuildSamples
中的指针相同。这可确保矢量具有正确的大小,而无需担心明确设置大小。这是一个浅薄的副本。然后,构造函数的主体设置BuildSamples
的每个元素,使其指向自身的克隆 - 从而完成深层复制。
构造函数BuildTree(const std::vector<Sample *> &)
可以以类似的方式实现。
注意:假设您的类正在实现一个非平凡的复制构造函数(用于执行深层复制)和一个要进行清理的析构函数,您还需要实现一个赋值运算符BuildTree &operator=(const BuildTree &)
。为了解释原因,请查看“三规则”。
答案 3 :(得分:0)
在处理指针并避免由于调用析构函数而导致正在运行的程序崩溃时,必须使用深度复制!深度复制允许创建指向新分配空间的新指针。但是,当将对象作为向量中的R值传递时,最好使用move构造函数。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class example{
private:
int *pointer;
public:
//constructor
example(int d){
pointer = new int;
*pointer = d;
cout<<"Constructor Called"<<endl;
}
// deep copy
example(const example &source){
pointer = new int;
*pointer= *source.pointer;
cout<<"deep copy made"<<endl;
}
// Move Constructor
example(example &&source) noexcept :pointer{source.pointer}{
source.pointer = nullptr;
cout << "object moved"<<endl;
}
// Destructor
~example() {
delete pointer;
cout << "Destroyed"<<endl;
}
};
int main()
{
vector <example> vec;
vec.push_back(example{300});
vec.push_back(example{300});
vec.push_back(example{300});
vec.push_back(example{300});
return 0;
}