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’
,
Оба поведения являются правильными, безусловно, в соответствии со стандартом 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.
Других решений пока нет …