2009-04-23 93 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來代替。

如果您不能使該類默認可複製/賦值,也許可以通過聲明私有拷貝構造函數和賦值運算符來使其不可複製/賦值。

只有當以上都不可行時,才能實現自己的拷貝構造函數或賦值運算符。