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

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?

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

Временные ссылки, присвоенные константным ссылкам, живут до
ссылка выходит за рамки

Список исключений из §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’,

4

Решение

Оба поведения являются правильными, безусловно, в соответствии со стандартом 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.

2

Другие решения

Других решений пока нет …