如何做一个矢量<class objects * =“”>深层复制

时间:2017-08-16 00:03:41

标签: c++ pointers vector deep-copy c++98

当涉及到类对象的指针向量时,我遇到了编写规则三的问题。搜索和示例似乎并不适用。我有这三个类:

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就是我所拥有的。 请显示执行此操作所需的步骤。非常感谢您的时间和考虑。

4 个答案:

答案 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不支持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;
    }