2015-07-01 34 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