Временный объект не уничтожен правильно? - PullRequest
1 голос
/ 25 января 2012

См. Этот код здесь:

class test
{
    int n;
    int *j;
public:
    test(int m)
    {
        n = 12;
        j = new int; 
        cin >> *j;
    }

    void show()
    {
        cout << n << ' ' << *j << endl;
    }

    ~test()
    {
        delete j;
    }

};

int main()
{
    test var = 123;
    var.show();
    return 0;
}

В этой программе компилятор должен пожаловаться на двойное удаление j. Первое удаление выполняется при уничтожении временного объекта temporary(123). Второе удаление выполняется, когда объект var уничтожен. Но это работает нормально?

Означает ли это, что временный объект не вызывает деструктор?

Ответы [ 3 ]

8 голосов
/ 25 января 2012

Спорная линия такова:

test var = 123;

Соответствующим стандартным текстом (на который ссылаются эксперты в комментариях), я полагаю, является (8.5, "Заявители"):

Выбранная функция вызывается с выражением инициализатора в качестве аргумента; если функция является конструктором, то вызов инициализирует временную версию cv-unqualed-определенной версии целевого типа. Временное значение. Результат вызова (который является временным для случая конструктора) затем используется для прямой инициализации, в соответствии с приведенными выше правилами, объекта, который является местом назначения инициализации копирования. В некоторых случаях реализация позволяет исключить копирование, присущее этой прямой инициализации, путем создания промежуточного результата непосредственно в инициализируемый объект ;

Действительно, в 12.6 мы получаем пример этого:

complex f = 3;  // construct complex(3) using
                // complex(double)
                // copy it into f

Таким образом, при использовании = ваша реализация , вероятно, напрямую создает объект и полностью исключает промежуточный временный объект (и, как отмечалось в комментариях, большинство делает).

Этот класс не копирует должным образом, поэтому создание его копии (и освобождение копии и оригинала) приведет к двойному удалению (и сбоям, неопределенному поведению и т. Д.). Поскольку копии не создаются, этот сценарий не происходит выше.

2 голосов
/ 25 января 2012

Два момента: во-первых, в данном конкретном случае компилятору оптимизировать временный, путем явного разрешения стандарт. Все компиляторы, с которыми я знаком, делают. Вы можете проверить происходит ли это в вашем коде, определяя конструктор копирования и инструменты его.

Во-вторых, если временное не оптимизировано, ваш код имеет неопределенное поведение. Двойное удаление может иметь любое мыслимое поведение: немедленная авария, коррупция на арене свободного пространства (приводящая к намного позже сбой, если программа продолжает работать), никакого эффекта, что так или когда-либо еще. Тот факт, что вы не видите никаких симптомов не означает, что код правильный.

1 голос
/ 25 января 2012

Тот факт, что код не взорвался, не означает, что он правильный.

Ваш класс содержит ошибки в том смысле, что он может удвоить deletes, как вы описываете.

Например, изменив var.show(); на следующее:

    test(var).show();

делает код надежно взорван на моем компьютере.

Чтобы исправить, реализуйте конструктор копирования и оператор присваивания.

...