2017-01-14 5 views
1

У меня есть класс формыПочему деструктор называется многократным, когда объект класса, содержащий элемент указателя, передается по ссылке? Как это исправить?

class A 
{ 
    int **a; 
    //other members 
} 

В некоторой функции, я передать объект класса А, скажем, obj, по ссылке

void func(A &o); //function declaration 

и

func(std::ref(obj)); //function call 

Однако , Я получил следующую ошибку - double free or corruption (!prev)

В соответствии с связанным вопросом это происходит потому, что деструктор вызывается несколько раз для элемента-указателя, что является следствием того, что экземпляр-копия вызывается несколько раз при копировании, в результате чего попытка освобождения памяти уже освобождена. Однако, поскольку я передаю полный объект по ссылке, почему это должно произойти? Не следует ли просто скопировать адрес всего объекта?

Предложения по реализации конструктора копирования в форме, указанной в приведенной выше ссылке, и here не помогут, поскольку они предусматривают выделение свежего количества памяти всякий раз, когда объект копируется, тогда как я хотел бы передать объект и как в результате элемент указателя, по ссылке.

Я просмотрел this и this потенциальные дубликаты, но они не решили мою проблему.

на основе нескольких других ответов, я также попытался реализации деструктор в

~A() 
{ 
    delete[] a; 
} 

или

~A() 
{ 
    if(a) 
    { 
     delete[] a; 
    } 
} 

но и не решить эту проблему.

+1

Где-то в коде, который вы не указали, вы передаете свой объект по значению, поэтому сделана копия. Если вам нужна дополнительная помощь, покажите [MCVE] (http://stackoverflow.com/help/mcve) –

+1

Запретить копирование ctor, а оператор присваивания и компилятор скажут вам, где вы копируете данные по значению. – Slava

+0

@Slava Как мне это сделать? – GoodDeeds

ответ

0

Я решил проблему. Я возвращал объект класса из функции, которая вызывала конструктор копирования. Я упустил из виду тот факт, что объект будет передан по значению.

Комментарий от @IgorTandetnik частично отвечает на вопрос, насколько он подтвердил, что не было причин для проблемы, которую я наблюдал, за исключением того, что я упускал из виду пропуск, который происходит где-то.

Это answer по ссылке, приведенной в комментарии @Slava's, очень полезно для выяснения источника проблемы.

2

Пробовать A(A const&)=delete; и A(A&&o):a(o.a){a=nullptr;}. Это удаляет вашу копию ctor и записывает нераспределяющий перемещение ctor.

Удаленная копия ctor даст вам ошибки времени компиляции, если вы попытаетесь скопировать экземпляр своего класса. Как и в вашем случае, это приводит к катастрофе при разрушении, это кажется хорошей идеей.

Это перемещение ctor позволит вам безопасно возвращать экземпляры вашего класса из функций, если возвращаемое значение неявно или явно (std::move) перемещено.

Также рассмотреть

A& operator=(A&&o) { 
    if (this==&o) return *this; 
    std::swap(a,o.a); 
    delete[] o.a; 
    o.a=nullptr; 
    return *this; 
} 
A& operator=(A const&o)=delete; 

Который позволяет назначить A из другого переехал из-A.

Тот факт, что вы должны иметь дело с move/copy assign/construct при написании деструктора, называется правилом пять.

Тот факт, что вам следует избегать писать какие-либо из них, называется нормой нуля.

Чтобы избежать их написания, замените a на unique_ptr<int[]>. Теперь он генерирует ваши операции перемещения и деструктор для вас и автоматически удаляет ваши операции копирования.

 Смежные вопросы

  • Нет связанных вопросов^_^