2013-02-01 173 views
5

我有以下問題: 在myClass中,我想默認初始化一個指向yourClass的指針,並帶有一個新的yourClass地址。 不幸的是,如果我想在任何點刪除指針,我會得到一個(核心轉儲)。C++默認構造函數,用新對象初始化指針

class myClass 
{ 
     protected: 
     yourClass * yc; 

     public: 
     myClass() { yc = new yourClass(); } 

     myClass(yourClass * tyc) { delete yc; yc = tyc; } 

     ~myClass() { delete yc; yc = NULL; } 

     void setMyClass (yourClass * tyc) { delete yc; yc = tyc; } 

     void print() { yc->print(); } 
}; 

int main() 
{ 
    yourClass b (//parameter); 
    myClass * a = new myClass(); 
    a->print(); 
    a->setMyClass(&b) 
    a->print(); 

    delete a; 
    return 0; 
} 

a,的print()應該導致兩個不同的打印,具體取決於//參數。

我認爲你的類yc;而不是yourClass * yc,但我想知道它是否可能。

編輯: 我以下面的方式重新編寫代碼,它的工作原理。看起來很複雜,聰明的指針似乎很有希望,我仍然沒有應用「三大規則」。 這裏的代碼。謝謝大家。

class myClass 
{ 
     protected: 
     yourClass * yc; 
     bool dynamic; 

     public: 
     myClass() { dynamic = true; yc = new yourClass(); } 
     myClass (yourClass * tyc) 
     { 
      // dynamic init (like default) 
      if (tyc == NULL) { dynamic = true; yc = new yourClass(); } 
      // static use of yc 
      else { dynamic = false; yc = tyc; } 
     } 
     // because only if dynamic is true, we need to erase 
     ~blu() { if (dynamic) { delete yc; dynamic = false; } } 

     void setMyClass(yourClass* tyc) 
     { 
      // leaving unchanged if new-stuff is NULL or like old-stuff 
      if (tyc == yc || tyc == NULL) return; 
      else // treating dynamic and static differently 
      { 
      if (dynamic) // if flag is set, must be deleted 
      { 
       delete yc; yc = tyc; dynamic = false; 
      } 
      else // must not be deleted, dynamic is still false 
      { 
       yc = tyc; 
      } 
      } 
     } 
     void print() { yc->print(); } 
}; 
+0

這應該是可能的 - 你的類的析構函數包含什麼? – 1615903

+0

哦,我不認爲應該在參數化的構造函數中刪除yc。 – 1615903

回答

7

那是因爲你正試圖刪除太多:

  • 你在第二個構造函數刪除未分配的對象(刪除delete yc;
  • 您要刪除重新建立了新分配的對象,b。 delete a;將嘗試刪除指向b的指針,該指針是堆棧上的一個對象;會發生什麼取決於你的操作系統上(我期待一個例外/核心轉儲/其他)

編輯:還有一個問題,我看到.. a->setMyClass(NULL)

我建議:

  • this post智能指針
  • this blog post on RAII
  • 解釋堆棧與堆分配(靜態與動態?)的任何C/C++初級讀本
+0

解決第二個問題的方法可能是爲'ownsYc'存儲一個標誌,當調用setMyClass()時,您可以將其設置爲false,並且只有在該標誌爲真時纔在析構函數中刪除yc – Crog

+0

@Crog ... ummm。 ..是的,但它仍然是一個非常非常危險的設計。在C++中,我相信擁有RIIA總是更好;此外,還有智能指針(http://www.stroustrup.com/) –

+1

非常真實,它不安全。 – Crog

1

您違反了三條規則。

What is The Rule of Three?

而且這是災難的配方:

myClass(yourClass * tyc) { delete yc; yc = tyc; } 

如果tyc==yc會發生什麼?對。不漂亮:)

myClass(yourClass * tyc) { if (yc!=tyc) { delete yc; yc = tyc; } } 
+0

它比構造函數中的:)更加災難性,yc將永遠不會被初始化:如果幸運的話,它會刪除NULL(segfault);否則它的刪除一些隨機的東西 –

+0

因此,你提出的代碼將崩潰(假設編譯器初始化yc爲0 ...) –

+1

@ dema80我同意,我沒有時間去真正閱讀該代碼。對我感到羞恥。我只是認爲我會強調這個經典的陷阱,因爲它稍微微妙一些(即使是Scott Meyer曾經在一本書中發表過一個帶有這種類型bug的smartptr) – sehe

相關問題