【问题标题】:c++ mystic transfer of class arrayc++类数组的神秘转移
【发布时间】:2011-05-21 14:18:59
【问题描述】:
class Array
{
    double *mx; int mn;
public:

 Array();
~Array(){delete []mx};
 Array& operator-(Array& b);  //first right way
 Array operator -(Array b);  //wrong way, but I don't understand why
};

Array::Array ()
{ 
  mn=10;
  mx=new double[mn];
}

//first, works perfectly
Array& Array::operator -(Array& b)
{
    int i=0;

    for(i=0;i<mn ;i++)
       this->mx[i]-=b.mx[i];

  return *this;
 }


// here is Error

Array Array::operator -(Array b)
{ 
    int i=0;

    for(i=0;i<mn ;i++)
       this->mx[i]-=b.mx[i];

  }


int main() {
   Array x,b;
   x=x-b;
}

如果我使用第一个重载,一切正常。

但是如果我使用第二个,一切都编译得很好,但是当程序执行时,我收到很多这样的错误:

"c++ ** glibc detected *** double free or corruption" 

我不知道为什么会这样。

据我所知,当我调用Array Array::operator-(Array b)时,必须复制对象并且一切都必须很好,但是有错误。

好吧,我已经读到我必须分配在内存中同一位置的对象。但我试过这样做:

        Array Array::operator +(Array b)
 { Array c;
 int i=0;
 for(i=0;i<mn;i++) 
this->mx[i]+=b.mx[i];
 cout<<&this->mx<<" "<<&b.mx<<endl; 
exit(0);
 return c; }

我希望在内存中收到相同的地址....

答案是 0xbfb45188 0xbfb45178 为什么它们相等?

此外,当我在这里声明类的名称(A 对象)
编译器必须在堆栈中为对象提供新内存 我哪里错了?我不明白....

【问题讨论】:

  • 你的问题是?来源和问题应该分开 - 在发布此类内容之前,请先查看其他一些 C++ 问题。
  • 考虑复制构造,通过 const ref ....

标签: c++ memory dynamic parameters transfer


【解决方案1】:
Array Array::operator -(Array b)

此行将创建您的数组的副本。由于您没有复制构造函数,编译器只会复制所有字段,包括指针字段“mx”。现在你有两个对象都指向同一个分配的内存。当每个都被破坏时, delete [] 将被调用....

您需要编写一个复制构造函数或确保不发生复制。 要做到这一点,通过引用传递

Array Array::operator -(Array& b)

(这也应该是 const ......但这是一个不同的问题)

【讨论】:

  • 注意这里的返回值也应该是一个引用,即Array&amp; Array::operator- (Array&amp; b),避免在输出的时候复制
  • @bodes:错误。 operator- 应该返回一个新对象。
  • @Tomalak 特别是关于@JohnB 的最后一个代码 sn-p,关于确保不发生复制...取决于编译器优化的级别,按值返回可能会复制,不是吗?
  • @bodes:当然。那有什么问题呢?写a = b - c的时候,是要修改b还是c?不,您希望a 成为一个全新的对象。 (如果您在 operator- 中创建一个然后通过引用返回它,您将返回一个悬空引用。)
【解决方案2】:

你违反了rule of three

【讨论】:

    【解决方案3】:
    • operator- 应该参考,否则你正在执行不必要的复制。但是,它并不需要。它当然应该返回一个值,因为 - 在语义上为您提供了一个新对象。当您写c = a-b 时,您不会期望ab 会发生变化。
    • 如上所述,您不需要引用operator-,在第二个示例中,您按值获取。这没关系,除了你有第二个错误:
      • 您的Array 类有一个内部缓冲区,它在构造时news,在销毁时deletes (~Array)。
      • 但是,它确实没有有用户定义的复制构造函数,缓冲区不会自动为你复制;仅复制指针 mx
      • 因此,当您复制Array 时,您现在有两个 对象,其中一个指针mx 指向同一个缓冲区。当一个副本超出范围时,该缓冲区为deleted;一段时间后,另一个副本尝试做同样的事情,delete同一缓冲区两次是错误的。

    我的建议:

    • 将复制构造函数和operator= 写入您的类Array。非常重要。
    • 无论如何都要让operator- 参考。这更有意义。

    希望对您有所帮助。

    【讨论】: