浅拷贝问题!

时间:2010-02-26 20:37:21

标签: c++

看看下面的代码,你不需要阅读整个代码只需阅读复制构造函数和主程序的代码。
复制构造函数中的以下语句

//the statement below should do the shallow copy 
    ptr[currentsize++]=object.ptr[i];

这个语句应该在指针数组的情况下做一个浅表副本,所以请看复制构造函数的代码和我在代码中提到问题的主要函数。

#include<iostream.h>
template<typename t>
class vector
{
public:
    vector(int size);
    vector(const vector<t>&);
    void insert(t);
    void display()const;
    void makeEmpty();//sets all pointers to NULL
private:
    t* ptr;
    int size;
    int currentsize;
};
template<typename t>
vector<t>::vector<t>(int s)
{
    currentsize=0;
    size=s;
    ptr=new t[size];
}
//copy constructor
template<typename t>
vector<t>::vector<t>(const vector<t>& object)
{
    size=object.size;
    ptr=new t[size];
    currentsize=0;
    for(int i=0;i<object.currentsize;i++)
    {
        //the statement below should do the shallow copy 
        ptr[currentsize++]=object.ptr[i];
    }
}
template<class t>
void vector<t>::insert(t element)
{
    if(currentsize < size)
        ptr[currentsize++]=element;
}
template<class t>
void vector<t>::display()const
{
    for(int i=0;i<currentsize; i++)
    {
        cout<<ptr[i]<<endl;
    }
}
template<class t>
void vector<t>::makeEmpty()
{
    for(int i=0;i<currentsize;i++)
        ptr[i]=NULL;
}
main()
{
    vector<char*>object(10);
    char *array[]={"zia","arshad","muneeb"};
    object.insert(array[0]);
    object.insert(array[1]);
    object.insert(array[2]);
    vector<char*> object1=object;
    cout<<"displaying the new object"<<endl;
    object1.display();
    object.makeEmpty();//sets all pointers to NULL
    //now here the object 1 should be changed but its not 
    cout<<"again displaying object1"<<endl;
    object1.display();//still displaying the three names 

    cout<<endl;
    system("pause");

}

6 个答案:

答案 0 :(得分:2)

您没有在object1中将指针更改为NULL,这是您希望在调用display时看不到任何结果的对象。由于object1仍然包含在其中的有效地址,因此您当然仍会看到结果,因为类型t的数组尚未被销毁/解除分配。

如果在makeEmpty()中你正在销毁/破坏对象,那么当你调用object1.display()时,你会得到未定义的行为(可能是SEGFAULT);作为指针,虽然它们仍然包含在其中的地址,但它们指向被破坏的内存是无效的。

答案 1 :(得分:2)

要了解要复制的内容,请将显示功能修改为:

template<class t>
void vector<t>::display()const
{
    for(int i=0;i<currentsize; i++)
    {
        cout<<(void* )&ptr[i] << ": " << ptr[i]<<endl;
    }
}

这不仅会显示指针的内容(作为字符串),还会显示指针的存储位置。

然后,您应该修改程序以执行object.display()。然后,您将看到指针有两个副本。当您使用makeEmpty()将指针清零时,您只需修改指针的一个副本。

答案 2 :(得分:1)

副本 浅w.r.t.实际的字符串数据,但不是字符串指针。字符串仍然存在于内存中;对第一个对象中的指针执行任何操作都不会更改第二个对象中的指针。

尝试将ptr[i]=null函数中的makeEmpty()更改为strcpy(ptr[i], "a"),您应该会在object2中看到它们(以及原始char *array[])。

如果您想要一个符合您需要的实际浅色副本,只需使用ptr = object.ptr

答案 3 :(得分:0)

你得到了你所写的。您的复制会生成阵列的副本。你不应该期望第一个向量的变化触及第二个向量。

请注意,您已删除指向第一个向量中字符串的指针。在第二个他们保持完整。

答案 4 :(得分:0)

对于浅层副本,只需执行:

ptr = object.ptr;
复制构造函数中的

你像在那里一样循环通过ptr的唯一原因是专门做一个深层复制......

编辑:

当你这样做时明白:

ptr=new t[size];

你要为ptr分配一个大小为“size * sizeof(t)”的新内存块。

并且

ptr[currentsize++]=object.ptr[i];

将object.ptr [i]的内容复制到ptr [currentsize]。

您也可以省略对new的调用并将该行更改为:

&ptr[currentsize++]=&object.ptr[i];

答案 5 :(得分:0)

不要增加currentsize

//ptr[currentsize++]=object.ptr[i];
ptr[i]=object.ptr[i];