4

C++продления срока временного по константной ссылке

Я пытаюсь понять, как константные ссылки продлить срок службы временных. Я запускаю код из фрагмента в one of the answers to What are the differences between pointer variable and reference variable in 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 вызванный отсутствием копирования, поэтому я попытался выяснить, может ли отключение копирования elision на g ++ с fno-elide-constructors дать тот же результат, что и VC11. (Я не думаю, что копия elision может быть переключена в VC11.) Но g ++ дает результат ответчика, независимо от установки флага.

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

There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression...

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:

...

ли результат VC11 имеют ничего общего с копией элизии? Это ошибка VC11?

Ответчик утверждает:

temporaries assigned to const references live until the const reference goes out of scope

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

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

EDIT:

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

#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"); 
} 

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

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’.

+0

Не существует никакого копирования, поскольку есть только * один * объект. –

+0

'const' не имеет ничего общего с продлением жизни. Любая ссылка будет сделана. Это просто, что ссылки не-const lvalue не могут связываться с rvalues, поэтому их никогда нельзя использовать таким образом. –

+0

@KerrekSB: привязка временной ссылки 'const' может привести к созданию копии.Самый простой способ проверить, есть ли созданная копия, - это инструмент для конструктора копирования. –

ответ

2

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

Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const). [Example: ...]

  • If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation-defined):

    — The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

    — A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

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

+0

»« Оба поведения правильные », вы имеете в виду, что вывод VC11 и g ++ верен для примера с ссылкой на const или для примера с ссылкой на неконстантную ссылку? Кроме того, я добавил копию и перемещение ctors (см. EDIT). Если пример VC11 - это случай - временный тип «cv1 T2» [sic], и вызывается конструктор для копирования всего объекта rvalue во временный. Ссылка привязана к временному ... '; означает ли это, что VC11 elides здесь, так как он не выводит 'copy ctor' или' move ctor', но не тогда, когда я не определяю свою собственную копию и не перемещаю ctors? – CodeBricks