簡體   English   中英

C++ 復制構造函數 - 指針分段錯誤的深層復制

[英]C++ Copy Constructor - Deep Copy of Pointers Segmentation Fault

我最近開始通過高級計算機科學基礎 MOOC 學習 C++。 我們有一個在隱藏的 .h 文件中聲明的挑戰(不能更改),我們需要編寫在 .h 文件中初始化的所有成員函數/構造函數/析構函數。

為避免作弊或任何為我做工作的人,如果有人能幫助解釋我做錯了什么以及我正在做什么導致分段錯誤,我將不勝感激。 我已經搜索並搜索了所有深層與淺層復制指南,但似乎無法理解我做錯了什么。

這是 .h 文件:

  class Pair {
    public:
      int *pa,*pb;
      Pair(int, int);
      Pair(const Pair &);
      ~Pair();
   };

從中要指出的兩件事是 pa/pb 是指向整數的指針,而不僅僅是整數,並且即使我閱讀了解釋是否有副本的“三巨頭規則”,也沒有賦值運算符的位置構造函數或析構函數我也應該有賦值運算符。

繼續前進,我嘗試了很多方法來使其工作並包含大量診斷消息,並且可以看到我搞砸的地方,但不明白為什么或我該做什么。

自定義構造函數我認為這沒問題:

 Pair::Pair (int a,int b) {
      int *pa = new int(a);
      int *pb = new int(b);
      std::cout << "pa points to value : " << *pa <<std::endl;
      std::cout << "pb points to value : " << *pb <<std::endl;
      std::cout << "custom constructor resolved "<<std::endl;
    }

Copy Constructor請原諒我只是想排除故障的所有評論。

    Pair::Pair(const Pair &obj) {

    int *const * a = &obj.pa;
    int *const * b = &obj.pb;
    int *pa = new int;
    int *pb = new int;
    pa = *a;
    pb = *b;

    std::cout << "obj.pa address is : " << &obj.pa <<std::endl;
    std::cout << "obj.pb address is : " << &obj.pb <<std::endl;
    std::cout << "obj.pa points at : " << obj.pa <<std::endl;
    std::cout << "obj.pb points at : " << obj.pb <<std::endl;

    std::cout << "pa address is : " << &pa <<std::endl;
    std::cout << "pb address is : " << &pb <<std::endl;
    std::cout << "pa is pointing at : " << pa <<std::endl;
    std::cout << "pb is pointing at : " << pb <<std::endl;
    std::cout << "copy constructor called "<<std::endl;
     }

析構函數我認為我在這方面做得不錯:

    Pair::~Pair() {
      delete pa; pa = nullptr;
      std::cout << "pa deleted " << std::endl;

      delete pb; pb = nullptr;
      std::cout << "pb deleted " << std::endl;
    }

主要系列測試

int main() {
  Pair p(15,16);
  Pair q(p);
  Pair *hp = new Pair(23,42);
  delete hp;

  std::cout << "If this message is printed,"
    << " at least the program hasn't crashed yet!\n"
    << "But you may want to print other diagnostic messages too." << std::endl;
  return 0;
}

看看這個,程序會創建一對 p; 然后創建一個深拷貝對q; 然后創建一個指向對 hp 的指針,該指針指向堆上的一對 23,42; 然后刪除指向對 hp 的指針。 除了復制構造函數之外,一切似乎都可以正常編譯和運行。 主要問題是 &obj.pa 似乎只是拉動對象 obj 的指針 *pa 指向的地址,而不是檢索實際的解除引用值。

此處的附加信息是執行 .main 時的終端輸出(添加附加注釋):

pa points to value : 15            // pair p.pa correct
pb points to value : 16            // pair p.pb correct
custom constructor resolved        // pair p made
obj.pa address is : 0x7fff1887c780 // address original object pointer pa stored 
obj.pb address is : 0x7fff1887c788 // address original object pointer pb stored
obj.pa points at : 0x2             // address pointer obj pa is directed to (I want the value not this)
obj.pb points at : 0x40102d        // address pointer obj pb is directed to (I wand the value not this)
pa address is : 0x7fff1887c728     // pa address on stack
pb address is : 0x7fff1887c730     // pb address on stack
pa is pointing at : 0x2            // address value copied not address itself
pb is pointing at : 0x40102d       // address value copied not address itself
copy constructor called            // copy constructor runs through albeit incorrect
pa points to value : 23            // hp.pa
pb points to value : 42            // hp.pb
custom constructor resolved        // constructor made on heap from pointer hp
pa deleted deleted original pa     // (made from pointer to pair hp)
pb deleted deleted original pa     // (made from pointer to pair hp)
If this message is printed, at least the program hasn't crashed yet!
But you may want to print other diagnostic messages too.
pa deleted                         // deleted original pa (made from pair p)
pb deleted                         // deleted original pb (made from pair p)

我跑了一遍,畢竟執行得到“分段錯誤”,我不太明白。 而且在 C++ 中這么早,我什至對我的術語沒有信心來幫助我的搜索能力。

您有兩個重大錯誤。

首先,您在構造函數中重新聲明指針。

Pair::Pair (int a,int b) {
    int *pa = new int(a);
    int *pb = new int(b);
    ...

應該

Pair::Pair (int a,int b) {
    pa = new int(a);
    pb = new int(b);
    ...

通過重新聲明指針,您將指針隱藏在要分配給的類中,而是分配給僅存在於構造函數中的局部變量。

復制構造函數中的問題完全相同。

其次,當您執行復制構造函數時,您不會復制右側指針的內容。 您正在復制指針本身。

它實際上比這容易得多,只需修改其他構造函數中的代碼即可。

Pair::Pair(const Pair &obj) {
    pa = new int(*obj.pa);
    pb = new int(*obj.pb);

與其他構造函數中的代碼相同,除了我們使用obj中的值而不是參數中的值初始化整數。

或者,如果您更喜歡較小的步驟

Pair::Pair(const Pair &obj) {
    int a = *obj.pa;
    int b = *obj.pb;
    pa = new int(a);
    pb = new int(b);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM