Временный объект не уничтожен правильно?

Смотрите этот код здесь:

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 ответа

Решение

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

test var = 123;

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

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

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

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

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

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

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

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

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

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

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

    test(var).show();

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

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

Другие вопросы по тегам