Продление жизни временного по константной ссылке

C++

Я пытаюсь понять, как ссылки на const продлевают жизнь временных пользователей. Я запускаю код из фрагмента в одном из ответов на вопросы. Каковы различия между переменной указателя и ссылочной переменной в C++? и получил противоречивые результаты между VC11 и g++ 4.8. Я расширил фрагмент здесь:

#include <stdio.h>

struct scope_test
{
    ~scope_test() { printf("scope_test done!\n"); }
};

int main()
{
    const scope_test& test = scope_test();
    printf("in scope\n");
}

Ответчик получил результат:

in scope
scope_test done!

Я попробовал это в VC11 и получил это:

scope_test done!
in scope
scope_test done!

Я предположил, что результат VC11 был вызван отсутствием разрешения копирования, поэтому я попытался проверить, отключено ли разрешение копирования на g ++ с fno-elide-constructors даст тот же результат, что и VC11. (Я не думаю, что разрешение на копирование может быть переключено в VC11.) Но g ++ дает результат ответчика независимо от установки флага.

Стандарт C++11, ISO/IEC 14882:2011(E), §12.2/4 и / 5 гласит:

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

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

...

Имеет ли результат VC11 какое-либо отношение к копированию? Это ошибка VC11?

Ответчик заявляет:

Временные значения, присвоенные ссылкам const, сохраняются до тех пор, пока ссылка на const не выходит из области

Список исключений из §12.2/5 не исключает non-const ссылка. Чего мне не хватает в Стандарте?

Удаление const в VC11 дает тот же результат, что и VC11 с const. Удаление const в g ++ дает error: invalid initialization of non-const reference of type ‘scope_test&’ from an rvalue of type ‘scope_test’, Почему есть разница?

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

Я добавил конструкторы копирования и перемещения и попытался:

#include <stdio.h>

struct scope_test
{
    scope_test() { printf("regular ctor\n"); }
    scope_test(const scope_test& src) { printf("copy ctor\n"); }
    scope_test(scope_test&& src) { printf("move ctor\n"); }
    ~scope_test() { printf("scope_test done!\n"); }
};

int main()
{
    const scope_test& test= scope_test();
    printf("in scope\n");
}

Независимо от переключения разрешения копирования, g ++ дает:

regular ctor
in scope
scope_test done!

VC11 дает то же самое, даже если const устранен. Если const удаляется из g++, g++ по-прежнему дает error: invalid initialization of non-const reference of type ‘scope_test&’ from an rvalue of type ‘scope_test’,

1 ответ

Решение

Оба поведения являются правильными, безусловно, в соответствии со стандартом C++03 (8.5.3 [dcl.init.ref] параграф 5):

В противном случае ссылка должна быть на энергонезависимый тип const (т. Е. Cv1 должен быть const). [Пример: ...]

  • Если выражение инициализатора является r-значением, с T2 типом класса, и "cv1 T1" совместим со ссылками с "cv2 T2", ссылка связывается одним из следующих способов (выбор определяется реализацией):

    - Ссылка привязана к объекту, представленному значением r (см. 3.10) или к подобъекту в этом объекте.

    - Создается временный объект типа "cv1 T2" [sic], и вызывается конструктор для копирования всего объекта rvalue во временный объект. Ссылка привязана к временному или подобъекту во временном.

Я думаю, что определение C++11 все еще позволяет делать копию, но формулировка не так явно позволяет копировать. В любом случае, VC++ не претендует на полную совместимость с C++11.

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