Деструктор вызывается на нежелательном объекте во время присваивания - PullRequest
5 голосов
/ 28 октября 2011
myClassVar = MyClass(3);  

Я ожидал вызова деструктора для ранее созданного myClassVar слева.
Но на самом деле он вызывается для нового объекта, созданного MyClass(3).

Мой полныйтестовый код и вывод следуют ..

edit

Как мне решить проблему?
Реализовать оператор присваивания?
MyClass на самом деле имеет указатели и MYSQL_STMT *, интересноя должен иметь дело с переменной MYSQL_STMT *.

Мне просто нужен объект MyClassVar (3), а не MyClassVar (), который был впервые создан при создании объекта ClientClass.

Я довольно часто сталкивался с этой ситуацией и спрашиваю себя, есть ли хороший способ сделать это.

#include <stdio.h>

class MyClass
{
public:
    MyClass() { printf("MyClass %p\n", this); }
    MyClass(int a) { printf("Myclass(int) %p\n", this); }
    ~MyClass() { printf("~MyClass %p\n", this); }

private:
    int mA;
};


class ClientClass
{
public:
    void Foo()
    {
        printf("before &myClassVar : %p\n", &myClassVar);
        myClassVar = MyClass(3); // this is the important line
        printf("after &myClassVar : %p\n", &myClassVar);
    }

private:
    MyClass myClassVar;
};

int main()
{   
    ClientClass c;
    c.Foo();
    return 0;
}

MyClass 0x7fff5fbfeba0
before &myClassVar : 0x7fff5fbfeba0
Myclass(int) 0x7fff5fbfeb70
~MyClass 0x7fff5fbfeb70 // <--- here destructor is called on the newly created object
after &myClassVar : 0x7fff5fbfeba0
~MyClass 0x7fff5fbfeba0

Ответы [ 4 ]

6 голосов
/ 28 октября 2011

Вот как критическая строка разбивается:

myClassVar = MyClass(3);

Сначала MyClass(3) вызывает конструктор и возвращает объект.

Во-вторых, myClassVar = копирует объект в myClassVar.

Тогда утверждение заканчивается.Объект (который является непосредственным) мертв, и поэтому вызывается деструктор.

РЕДАКТИРОВАТЬ:

Что касается того, как обойти это.Единственный способ, которым я могу придумать, - это использовать размещение нового .Я не уверен, есть ли лучшее решение, кроме создания метода "set".

2 голосов
/ 28 октября 2011

Как упоминалось в других публикациях, объект с пользовательским конструктором MyClass(3) уничтожается после операции присваивания myClassVar = MyClass(3).В этом случае вам не нужен пользовательский оператор присваивания, потому что сгенерированный им компилятор копирует элемент mA в уже существующий объект myClassVar.

Однако, поскольку MyClass определяет свой собственный деструктор, вы должны придерживаться правила из трех , которое требует, чтобы в таком случае вы также реализовали собственный оператор присваивания.

2 голосов
/ 28 октября 2011
myClassVar = MyClass(3);

myClassVar продолжает существовать после этой строки.Время жизни MyClass(3) заканчивается точкой с запятой.

1 голос
/ 28 октября 2011

Отвечая на ваше редактирование: как вы решаете какую проблему? Не ясно в чем проблема. Если вашему классу нужен деструктор (и нет полиморфизм в игре), он, вероятно, нуждается в операторе присваивания и конструктор копирования. Аналогично, при «отслеживании» конструкций и разрушения, вы, вероятно, должны предоставить оба, так как они будут быть названным.

В противном случае: если проблема в том, что вы создаете, а затем присваивать, а не строить с правильным значением немедленно, простой ответ «не делай этого». Компилятор делает то, что вы говорите к. Если вы напишите:

MyClass var;
var = MyClass(3);

у вас есть конструкция по умолчанию, за которой следует конструкция временное, назначение и уничтожение временного. если ты написать:

MyClass var(3);

или

MyClass var = 3;

у вас есть только одна конструкция. (Обратите внимание, что, несмотря на внешность, это нет назначения в последнем фрагменте. Только строительство.)

Для учеников эта разница проявляется в том, как вы пишете Конструктор:

ClientClass::ClientClass() { var = MyClass(3); }

- конструкция по умолчанию, за которой следуют создание, назначение и уничтожение временного;

ClientClass::ClientClass() : var( 3 ) {}

это просто конструкция с правильным значением. (Скорее всего, это вторая форма является предпочтительной.)

...