如何做一个矢量 深刻的副本

问题描述 投票:1回答:4

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

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-请注意:无法访问智能指针,shared_ptr或unique_ptr等.C ++ 98就是我所拥有的。请显示执行此操作所需的步骤。非常感谢您的时间和考虑。

c++ pointers vector deep-copy c++98
4个回答
1
投票

我注意到你把你的问题标记为;即使C ++ 98不支持std::中的智能指针,你当然可以使用Boost中定义的智能指针,例如: boost::shared_ptr。例如,不使用vector<Sample*>中的原始拥有指针,而是可以使用vector<boost::shared_ptr<Sample>>使代码更简单。

通过这种方式,复制和销毁操作将自动在引擎盖下实现。


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]));
    }
}

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 &)。为了解释原因,请查阅“三规则”。


0
投票

在处理指针并避免因调用析构函数而导致正在运行的程序崩溃时,必须使用Deep copy!深拷贝允许创建指向新分配空间的新指针。但是当在向量中将对象作为R值传递时,最好使用移动构造函数。

    #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;
    }
© www.soinside.com 2019 - 2024. All rights reserved.