2015-07-01 82 views
1

這個C++代碼有什麼問題?此運算符重載代碼有什麼問題?

它編譯,但它不運行。

#include <iostream> 

using namespace std; 

class MyClass 
{ 
private: 
    int *x; 
    int *y; 
public: 
    MyClass() 
    { 
     x = new int[1]; *x = 0; 
     y = new int[1]; *y = 0; 
    } 
    ~MyClass() 
    { 
     if(x != NULL) 
     { 
      delete [] x; 
      x = NULL; 
     } 
     if(y != NULL) 
     { 
      delete [] y; 
      y = NULL; 
     } 
    } 
    MyClass operator=(MyClass & rhs) 
    { 
     MyClass temp; 
     temp.Set(rhs.x[0], rhs.y[0]); 
     return temp; 
    } 
    void Set(int a, int b) 
    { 
     if(x != NULL) 
     {   
      *x = a; 
     } 
     if(y != NULL) 
     {   
      *y = b; 
     } 
    } 
    void Show() 
    { 
     cout<<x[0]<<y[0]<<endl; 
    } 
}; 

int main() 
{ 
    MyClass o1; 
    o1.Set(10, 20); 
    o1.Show(); 

    MyClass o2; 
    o2 = o1; 
    o2.Show(); 
} 

enter image description here

回答

4

雖然實際碰撞可通過陣列的失配的重新分配作爲由rlbond的回答提到引起的,還有另一種微妙的替代:

operator=返回一個拷貝(未如常規基準),使用其創建默認的拷貝構造函數。在這個例子中,它沒有被使用,所以創建了一個臨時的。臨時文件xy指向與副本相同的內存,因爲複製構造函數未定義。當臨時被破壞時,其xy被刪除 - 之後o2被銷燬,導致相同的內存被釋放兩次。

值得一提的是,這門課程還有很多可能出錯的地方,需要進一步的熱愛和關注。還值得一看,我們如何能找到這個錯誤。

下面是我通過pc-lint online linter推送時得到的結果。 請注意,這包括導致崩潰的問題以及需要修復的其他許多事情。

1 #include <iostream> 
2 
3 using namespace std; 
4 
5 class MyClass 
6 { 
7 private: 
8  int *x; 
9  int *y; 
10 public: 
11  MyClass() 
12  { 
13   x = new int[1]; *x = 0; 
14   y = new int[1]; *y = 0; 
15  } 
16  ~MyClass() 
17  { 
18   if(x != NULL) 
19   { 
20    delete x; 
21    x = NULL; 
22   } 
23   if(y != NULL) 
24   { 
25    delete y; 
26    y = NULL; 
27   } 
28  } 
29  MyClass operator=(MyClass & rhs) 
     _ 
30  { 

diy.cpp 30信息1722:類賦值運算符「MyClass的」參考不回

diy.cpp 30信息1720:類賦值運算符「MyClass的」有非常量參數

31   MyClass temp; 
32   temp.Set(rhs.x[0], rhs.y[0]); 
33   return temp; 
34  } 
35  void Set(int a, int b) 
36  { 
37   if(x != NULL) 
38   {   
39    *x = a; 
40   } 
41   if(y != NULL) 
42   {   
43    *y = b; 
44   } 
45  } 
46  void Show() 
47  { 
48   cout<<x[0]<<y[0]<<endl; 
49  } 
       _ 
13   x = new int[1]; *x = 0; 

diy.cpp 13信息1733:新構造中的類 'MyClass的' 它沒有拷貝構造函數

20    delete x; 

diy.cpp 20警告424:不適當的解除分配(刪除)關於 '新[]' 數據

25    delete y; 

DIY。CPP 25警告424:不適當的解除分配(刪除)關於 '新[]' 數據

33   return temp; 

diy.cpp 33信息1772:賦值運算符 'MyClass的::運算=(MyClass的&)' 沒有返回*此

34  } 

diy.cpp 34警告1529:符號 'MyClass的::運算=(MyClass的&)' 不是第一檢查分配給這個

diy.cpp 34信息1764:參考參數 'RHS'(線29)可以被聲明爲const ref

diy.cpp 34警告1539:成員 'MyClass的:: X'(第8行)沒有被賦值運算符

diy.cpp 34警告1539分配:成員 'MyClass的:: Y'(第9行)不通過賦值操作符分配

48   cout<<x[0]<<y[0]<<endl; 

diy.cpp 48警告613:文件diy.cpp:線37]

在左參數到操作者 '['[參考可能的使用空指針的 'MyClass的:: X'

diy.cpp 48警告613:在運算符'['[參考:file diy.cpp:li'的左參數中可能使用空指針'MyClass :: y' NE 41]

49  } 

diy.cpp 49信息1762:會員功能 'MyClass的::展(無效)' 可以由常量

50 }; 
51 
52 int main() 
53 { 
54  MyClass o1; 
55  o1.Set(10, 20); 
56  o1.Show(); 
57 
58  MyClass o2; 
59  o2 = o1; 
60  o2.Show(); 
61 } 
62 
+0

嘿,這是一個不錯的工具! – rlbond

+0

我很驚訝!對我來說這是一個新的願景。它可以或應該專業使用嗎? – anonymous

+0

他們有一個商業PCLint產品,可以專業使用。它比在線演示功能強大得多,能夠處理整個項目。 (我不以任何方式附屬於他們 - 只是欣賞他們的產品)。 –

4

唯一明顯的錯誤,我可以看到的是,你分配xy爲數組,所以你需要使用delete [] x;代替delete x;,與同爲y。斷言似乎也表明它在刪除期間拋出,因爲斷言消息中提到的文件是dbgdel.cpp,它正在檢查塊類型是否有效(最有可能的是,它檢查要刪除的塊是否實際上是一個數組塊或單個實例)

你也不需要這些檢查對NULL; new總是成功或引發異常。

的更多信息:delete vs delete[] operators in C++

編輯:另外,你需要定義一個拷貝構造函數。請參閱rule of three

+0

更正。還是行不通。 – anonymous

+1

我覺得它更微妙一點。我認爲'operator ='正在返回一個拷貝,它使用_default_拷貝構造函數,'operator ='返回的臨時文件正在被破壞,導致同一個內存被釋放兩次。 –

+0

啊,是的,這似乎是潛在的問題。 – rlbond