Membro de referência agregado e tempo de vida temporário
Dado este exemplo de código, quais são as regras relativas ao tempo de vida da cadeia temporária que está sendo passadaS
.
struct S
{
// [1] S(const std::string& str) : str_{str} {}
// [2] S(S&& other) : str_{std::move(other).str} {}
const std::string& str_;
};
S a{"foo"}; // direct-initialization
auto b = S{"bar"}; // copy-initialization with rvalue
std::string foobar{"foobar"};
auto c = S{foobar}; // copy-initialization with lvalue
const std::string& baz = "baz";
auto d = S{baz}; // copy-initialization with lvalue-ref to temporary
De acordo com o padrão:
N4140 12,2 p5.1 (removido em N4296)
Um limite temporário a um membro de referência no ctor-inicializador de um construtor (12.6.2) persiste até que o construtor saia.
N4296 12.6.2 p8
Uma expressão temporária vinculada a um membro de referência em um inicializador de mem está incorreta.
Portanto, ter um construtor definido pelo usuário como[1]
definitivamente não é o que queremos. Ele deveria estar mal formado no C ++ 14 mais recente (ou é?) Nem o gcc nem o clang avisaram sobre isso.
Isso muda com a inicialização agregada direta? Parece que, nesse caso, a vida útil temporária é prolongada.
Agora, com relação à inicialização de cópia,Construtor de movimentação padrão e membros de referência afirma que[2]
é gerado implicitamente. Dado o fato de a movimentação poder ser elidida, a mesma regra se aplica ao construtor de movimentação gerado implicitamente?
Qual dosa, b, c, d
tem uma referência válida?