2009-04-23 153 views
11

我最近发现,当我有一个类内的指针,我需要指定一个复制构造函数。复制构造函数与指针

为了解这一点,我做了以下简单的代码。它编译,但执行复制构造函数时给我运行时错误。

我想复制只是复制对象的指针的值,但避免分配相同的地址。

那么,这里有什么问题?

class TRY{ 
     public: 
     TRY(); 
    ~TRY(); 
     TRY(TRY const &); 

     int *pointer; 

     void setPointer(int); 
    }; 


    void TRY::setPointer(int a){ 
     *pointer = a; 

     return; 
    } 


    TRY::TRY(){} 


    TRY::~TRY(){} 


    TRY::TRY(TRY const & copyTRY){ 
     int a = *copyTRY.pointer; 
     *pointer = a; 
    } 



    int main(){ 

     TRY a; 
     a.setPointer(5); 

     TRY b = a; 

     b.setPointer(8); 

     cout << "Address of object a = " << &a << endl; 
     cout << "Address of object b = " << &b << endl; 

     cout << "Address of a.pointer = " << a.pointer << endl; 
     cout << "Address of b.pointer = " << b.pointer << endl; 

     cout << "Value in a.pointer = " << *a.pointer << endl; 
     cout << "Value in b.pointer = " << *b.pointer << endl; 

     return 0; 
    } 

我将这个概念用于其中有很多指针的类,其中我需要将所有值从一个对象复制到另一个。这个代码最初需要复制,所以我想保留复制的可能性(我不会将复制构造函数隐藏为私有)。

此外,我需要实现的真正的类有10个指针,它可能随时间而改变。是不是有一个有些更聪明的办法在C++?深拷贝构造函数...

回答

12

随着int* pointer刚才定义一个指针,但还没有分配的任何内存的声明。首先,你应该通过分配一些像这样的内存来指向正确的内存位置:int* pointer = new int。然后在复制构造函数中,您必须为复制的对象分配内存。另外,不要忘记在析构函数中使用delete释放内存。

我希望这个例子可以帮助:

class B 
{ 

public: 
    B(); 
    B(const B& b); 
    ~B(); 
    void setVal(int val); 

private: 
    int* m_p; 
}; 

B::B() 
{ 
    //Allocate the memory to hold an int 
    m_p = new int; 

    *m_p = 0; 
} 

B::B(const B& b) 
{ 
    //Allocate the memory first 
    m_p = new int; 

    //Then copy the value from the passed object 
    *m_p = *b.m_p; 
} 

B::~B() 
{ 

    //Release the memory allocated 
    delete m_p; 
    m_p = NULL; 
} 

void B::setVal(int val) 
{ 
    *m_p = val; 
} 
+3

不要忘记在为它分配新对象之前先删除m_p。 – xtofl 2009-04-23 14:18:39

+0

我没有定义赋值操作符,它只是一个拷贝构造函数。因此不需要删除m_p。 – Naveen 2009-04-23 14:21:32

1

,如果它有一个指针指向一个普通类型,然后

A::A(const A& a): 
    pointer_(new int(*a.pointer_)) 
{ 
} 

如果它有一个指针,一些基础类然后

A::A(const &a): 
    pointer_(a.pointer_->clone()) 
{ 
} 

克隆的实施prototype pattern

不要忘记删除指针在析构函数

A::~A() 
{ 
    delete pointer_; 
} 

要解决你的榜样

TRY::TRY(TRY const & copyTRY){ 
    int a = *copyTRY.pointer; 
    pointer = new int(a); 
} 
3

如果你想要做一个深拷贝,你当然也必须分配新的内存来保存值。如果原始文件有一个指向int的指针,并且不希望副本使用相同的指针值,则必须分配新的内存来保存一个int值,然后将值复制到那里。

你的例子不是很清楚,它没有显示你的拷贝构造函数的实现,或者pointer成员如何被初始化。

1

您的问题是在这条线就在这里:

*pointer = a; 

所有,通常发生在你的默认构造函数的东西,还没有发生,包括内存*pointer分配。

此修复程序是为整数分配内存。您可以使用malloc和朋友或new来做这件事,但要确保它与默认构造函数中使用的方法相同,因为只有一个析构函数,并且调用必须匹配。

1

如果一个成员(浅)副本是好的,那么你不必做任何事情。如果您想要深度复制,则必须为所有成员的副本分配新的存储空间。

0

在编写复制构造函数时,应该为所有成员分配内存。 你的情况:

TRY::TRY(TRY const & copyTRY){ 
    pointer = new int(*(copyTry.pointer)); 
} 

操作=是有点相似,但没有内存分配。

TRY& operator=(TRY const& otherTRY){ 
     this->a = *(otherTry.pointer) 
     return *this 
} 
8

我最近发现,当我 类中有一个指针,我需要 指定拷贝构造函数。

这并非完全正确。当你的类中有指针并且使用new分配内存时,那么你不得不担心复制构造函数。另外,不要忘记赋值运算符和析构函数。 您必须删除使用delete分配的内存。它们被称为Law Of The Big Three

例子:

~Matrix(); //Destructor 
    Matrix(const Matrix& m); //Copy constructor 
    Matrix& operator= (const Matrix& m); //Assignment operator 
1

我最近发现,当我 类中有一个指针,我需要 到更多的往往不是它是一个指定拷贝构造函数

通过声明它(和assigment运算符)是私有的而不是实现它是一个好主意。

0

通常情况下,如果你需要编写一个拷贝构造函数或赋值操作符,你会做错某些事情。将复制构造函数和赋值操作符留给标准库的实现者。撰写您已经可复制和可分配的元素的类,而不必自己编写。

例如,也许该int *成员应该是一个std :: vector来代替。

如果您不能使该类默认可复制/赋值,也许可以通过声明私有拷贝构造函数和赋值运算符来使其不可复制/赋值。

只有当以上都不可行时,才能实现自己的拷贝构造函数或赋值运算符。