【问题标题】:std vector C++ -- deep or shallow copy标准向量 C++——深拷贝或浅拷贝
【发布时间】:2012-07-06 02:18:45
【问题描述】:

我想知道是否复制向量我正在复制向量及其值(而这不适用于数组,并且深度复制需要循环或 memcpy)。

你能提示解释吗?

问候

【问题讨论】:

  • 不要将memcpy 用于vector。 vector 中包含的对象可能不是 POD,它们可能是具有虚函数的类。使用std::copy 或简单的vector<T>vector<T> 赋值。
  • “深”与“浅”的区别在默认为值语义并且不会试图隐藏它使用指针这一事实的语言中没有多大意义(因此指针是具有自己值的对象,与它们引用的对象不同)。复制总是按价值的,这是否构成“深度”复制与“浅”复制取决于您的定义。

标签: c++ vector copy std deep-copy


【解决方案1】:

每次复制矢量时,您都在进行深度复制。但是如果你的向量是一个指针向量,你得到的是指针的副本,而不是指向的值

例如:

std::vector<Foo> f;
std::vector<Foo> cp = f; //deep copy. All Foo copied

std::vector<Foo*> f;
std::vector<Foo*> cp = f; //deep copy (of pointers), or shallow copy (of objects).
//All pointers to Foo are copied, but not Foo themselves

【讨论】:

  • +1 我将第二个示例视为浅拷贝。 int *a, *b; a=b; // Shallow copy。在向量的情况下,我们不是在做这样的事情吗?顺便说一句,它的 deep 而不是 deap :)
  • 有时当我看到这些术语在不同的帖子中以不同的方式使用时,我会感到困惑。可以说,在指针的情况下,它们是浅拷贝;两者似乎都是正确的,这取决于您如何解释它们。
  • 混淆可能来自“指针”和“指针”之间的缺失区别。指针只是普通的对象,它们确实按照人们期望的方式复制。人们感到困惑的是pointees
  • 不是靠Foo的拷贝构造函数的实现,还是拷贝赋值?它不是最终被调用的那些之一吗? (在那种情况下,哪个?)
  • @user833771 问题与unique_ptr 无关。 unique_ptr是不能复制的,可以move或者新建一个深拷贝内容。
【解决方案2】:

Vector 将调整大小以便为对象提供足够的空间。然后它将遍历对象并为每个对象调用默认的复制运算符。

这样,向量的副本就“深”了。向量中每个对象的副本是为默认复制运算符定义的。

在示例中...这是错误的代码:

#include <iostream>
#include <vector>

using namespace std;

class my_array{
public:
    int *array;
    int size;
    my_array(int size, int init_val):size(size){
        array = new int[size];
        for(int i=0; i<size; ++i)
            array[i]=init_val;
    }
    ~my_array(){
        cout<<"Destructed "<<array[0]<<endl;
        if(array != NULL)
            delete []array;
        array = NULL;
        size = 0;
    }

};

void add_to(vector<my_array> &container){
    container.push_back(my_array(4,1));
}

int main(){

    vector<my_array> c;
    {
        my_array a(5,0);
        c.push_back(a);
    }
    add_to(c);
    //At this point the destructor of c[0] and c[1] has been called.
    //However vector still holds their 'remains'
    cout<<c[0].size<<endl; //should be fine, as it copies over with the = operator
    cout<<c[0].array[0]<<endl;//undefined behavior, the pointer will get copied, but the data is not valid
    return 0;
}

这是更好的代码:

#include <iostream>
#include <vector>

using namespace std;

class my_array{
public:
    int *array;
    int size;
    my_array(int size, int init_val):size(size){
        cout<<"contsructed "<<init_val<<endl;
        array = new int[size];
        for(int i=0; i<size; ++i)
            array[i]=init_val;
    }
    my_array(const my_array &to_copy){
        cout<<"deep copied "<<to_copy.array[0]<<endl;
        array = new int[to_copy.size];
        size = to_copy.size;
        for(int i=0; i<to_copy.size; i++)
            array[i]=to_copy.array[i];
    }

    ~my_array(){
        cout<<"Destructed "<<array[0]<<endl;
        if(array != NULL)
            delete []array;
        array = NULL;
        size = 0;
    }

};

void add_to(vector<my_array> &container){
    container.push_back(my_array(4,1));
}

int main(){

    vector<my_array> c;
    {
        my_array a(5,0);
        c.push_back(a);
    }
    add_to(c);
    //At this point the destructor of c[0] and c[1] has been called.
    //However vector holds a deep copy'
    cout<<c[0].size<<endl; //This is FINE
    cout<<c[0].array[0]<<endl;//This is FINE
    return 0;
}

【讨论】:

  • 更好的是,仍然是五法则。 :) (你使用了旧的三法则)
  • 实际上他实施了二分法:)
猜你喜欢
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
  • 2015-01-13
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多