c ++ мистическая передача массива классов - PullRequest
1 голос
/ 21 мая 2011
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" 

http://s41.radikal.ru/i091/1105/e1/2349397c04a2.png

Я не могу понять, почему это происходит.

Как я понимаю, когда я вызываю 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 почему они равны?

далее, когда я объявляю здесь имя класса (объект)
компилятор должен дать новую память в стеке для объекта, где я ошибаюсь?я не понимаю ....

Ответы [ 3 ]

3 голосов
/ 21 мая 2011

Вы нарушили правило трех .

3 голосов
/ 21 мая 2011
Array Array::operator -(Array b)

Эта строка создаст копию вашего массива. Поскольку у вас нет конструктора копирования, компилятор просто сделает копию всех полей, включая поле указателя «mx». Теперь у вас есть два объекта, оба указывают на одну и ту же выделенную память. Когда каждый из них будет уничтожен, будет вызвано delete [] ....

Вам необходимо либо написать конструктор копирования, либо убедиться, что копирование не выполняется. Для этого пройдите по ссылке

Array Array::operator -(Array& b)

(Возможно, это тоже должно быть const ... но это другая проблема)

1 голос
/ 21 мая 2011
  • operator- следует взять ссылку, в противном случае вы выполняете ненужные копии.Тем не менее, не нужно для.Это, безусловно, должно возвращать значение, потому что - семантически дает вам новый объект.Когда вы пишете c = a-b, вы не ожидаете, что a или b изменится.
  • Как отмечалось выше, вам не нужно , чтобы взять ссылку на operator- и во втором примере вы берете по значению.Это нормально, за исключением того, что у вас есть вторая ошибка:
    • Ваш класс Array имеет внутренний буфер, который он new строит, и delete s, когда он уничтожается(~Array).
    • Однако он не имеет пользовательский конструктор копирования, и буфер не копируется автоматическидля тебя;копируется только указатель mx.
    • Итак, когда вы копируете Array, у вас теперь есть два объекта суказатель mx, указывающий на тот же буфер.Когда одна копия выходит из области видимости, этот буфер равен delete d;Через некоторое время другая копия пытается сделать то же самое, и delete дважды в одном и том же буфере возникает ошибка.

Мои предложения:

  • Напишите конструктор копирования и operator= в свой класс Array.Очень важно.
  • В любом случае operator- возьмите ссылку.Это имеет смысл.

Надеюсь, это поможет.

...