c ++ 17: временный объект никогда не уничтожается - PullRequest
3 голосов
/ 06 марта 2019
struct Base {
    Base() {
        std::cout << "Inside:  " << __PRETTY_FUNCTION__ << std::endl;
    }
    ~Base() {
        std::cout << "Inside:  " << __PRETTY_FUNCTION__ << std::endl;
    }
};

struct BaseWrapper {
    const Base &b;
};

int main()
{
    {
        auto *w = new BaseWrapper{{}};
        std::cout << "Inside:  " << __PRETTY_FUNCTION__ << std::endl;
        delete w;
    }
    return 0;
}

Приведенный выше код работает, как я и ожидал, когда я компилирую его с C ++ 11 или C ++ 14, но когда я компилирую его с C ++ 17, он дает мне что-то вроде этого:

Inside:  Base::Base()                                                                                                                                                              
Inside:  int main()

Как видите, Base :: ~ Base () никогда не вызывался.Что не имеет большого смысла для меня.Я тестировал этот код с GCC 7.3.0 на Ubuntu 18.04.1 LTS, а также с OnlineGDB .Все они дают одинаковый результат.

Мне просто интересно, если это новая функция в C ++ 17 или это ошибка?

Обновление: IЯ хорошо знаю, что w->b - это свисающая ссылка.На самом деле, я специально написал этот кусок кода, чтобы показать это.Затем я обнаружил эту проблему во время тестирования.

Что я действительно хочу знать, так это то, насколько серьезна эта проблема, если мне нужно придерживаться GCC 7.3?или есть ли другие способы воспроизвести ту же проблему?или отчет о дефекте?

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Очевидно, что созданный, но не уничтоженный временный файл - это ошибка компилятора - если только стандарт не говорит, что поведение не определено.Однако пример хорошо определен.Соответствующие правила из стандарта [class.teilitary]:

Когда реализация вводит временный объект класса, который имеет нетривиальный конструктор ([class.default.ctor], [class.copy.ctor]), он должен обеспечить вызов конструктора для временного объекта.Точно так же деструктор должен быть вызван для временного с нетривиальным деструктором ([class.dtor]).Временные объекты уничтожаются как последний шаг в оценке полного выражения ([intro.execution]), которое (лексически) содержит точку, в которой они были созданы....

Существует три контекста, в которых временные объекты уничтожаются в другой точке, чем конец полного выражения....

Третий контекст - это когда ссылка связана с временным объектом ...

Исключения из этого правила времени жизни:

  • ...

  • A временный , связанный со ссылкой в ​​новом инициализаторе ([expr.new]) сохраняется до завершения полного-выражение, содержащее новый инициализатор .

0 голосов
/ 06 марта 2019

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

Существуют странные правила продления времени жизни с совокупной инициализацией ссылочных членов.

Вы можете обновить свой компилятор или просто добавить BaseWrapper(Base const& bin):b(bin){} ctor и наблюдать, как ошибка исчезает.

...