Pergunta

É possível alterar o objeto temporário e passá-lo como argumento?

struct Foo {    
   Foo& ref() { return *this; }
   Foo& operator--() { /*do something*/; return *this; }
   // another members
};
Foo getfoo() { return Foo(); } // return Foo() for example or something else
void func_val(Foo x) {}
void func_ref(const Foo & x) {}

int main() {
   func_val(--getfoo());     // #1 OK?
   func_ref(getfoo());       // #2 OK?
   func_ref(getfoo().ref()); // #3 OK?
   // the following line is a real example 
   //    using --vector.end() instead of --getfoo()
   func_ref(--getfoo());     // #4 OK? 

   const Foo & xref = --getfoo(); //  Does const extend the lifetime ?
   func_ref(xref);     // #5 OK? 
   func_val(xref);     // #6 OK? 

}

Sabe-se que atribuir um objeto temporário à referência const prolonga a vida útil desse objeto temporário.E quanto às linhas 4 e 5 do meu código?É verdade que a referência x é sempre válida na função func_ref?Acontece que o operador-- retorna alguma referência e o compilador não vê nenhuma relação entre essa referência e o temporário que criamos.

Foi útil?

Solução

func_val(--getfoo());     // #1 OK?

Sim, ok.O operator-- é uma função-membro, que é chamada e que retorna a si mesma (e lvalue referindo-se a si mesmo).O objeto é então copiado para o parâmetro de func_val.Observe que a otimização do valor de retorno não pode ser aplicada, uma vez que o temporário criado por getfoo() estava anteriormente vinculado a uma referência.

func_ref(getfoo());       // #2 OK?

Sim, ok.A chamada getfoo() retorna um temporário que está vinculado à referência const.Um construtor de cópia é necessário, mas a chamada dele pode ser otimizada pela implementação.O temporário persiste até o final da expressão completa que contém a chamada para func_ref (toda a declaração da expressão aqui).

func_ref(getfoo().ref());

Sim, ok.Nenhum construtor de cópia é necessário, pois vinculamos a referência const não a um temporário, mas ao lvalue que representa o próprio objeto.

// the following line is a real example 
//    using --vector.end() instead of --getfoo()

Isso não é necessário para funcionar.Pense em uma situação em que vector.end() retorna um T* (permitido).Você não tem permissão para modificar valores de tipo que não seja de classe; portanto, nesse caso, isso seria mal formado.

func_ref(--getfoo()); 

Sim, ok.O argumento é avaliado como em #1, mas o lvalue resultante é passado diretamente e a referência const está vinculada a ele.Neste sentido é igual a #3 (exceto para o efeito colateral de diminuição).

const Foo & xref = --getfoo();

A redação padrão não é totalmente clara.Certamente pretende apenas prolongar a vida útil de objetos ainda não vinculados a uma referência.Mas no nosso caso, --getfoo() produz um lvalue referente a um objeto temporário que foi previamente vinculado a uma referência.Pode valer a pena enviar um relatório de defeito ao comitê (também posso ter perdido o texto que exige que o objeto temporário ainda não esteja vinculado a uma referência).

Em qualquer caso, o comportamento pretendido é destruir o temporário que resulta da getfoo() no final da inicialização xref, então xref se tornará uma referência pendente.

Acontece que o operador-- retorna alguma referência e o compilador não vê nenhuma relação entre essa referência e o temporário que criamos.

Exatamente (mas se aplica apenas à inicialização do xref que vai enlouquecer.Em todos os outros casos, o comportamento pretendido que você deseja (ou o que acredito que você deseja) é alcançado).

Outras dicas

Temporários sempre vivem a vida inteira cheio expressão em que eles são criados de qualquer maneira. Portanto, no declaração de expressão func_val(--getfoo());, a vida inteira do temporário devolvido pelo getfoo() A expressão não precisa de nenhuma extensão. A declaração não termina até depois func_val() voltou.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top