Esta pergunta é decorrente deste comentário: Explicação da vida útil do Lambda para corotinas C ++ 20
em relação a este exemplo:
auto foo() -> folly::coro::Task<int> {
auto task = []() -> folly::coro::Task<int> {
co_return 1;
}();
return task;
}
Portanto, a questão é se a execução da rotina retornada por foo
resultaria em UB.
"Chamar" uma função de membro (após o término da vida útil do objeto) é UB: http://eel.is/c++draft/basic.life#6.2
... qualquer ponteiro que represente o endereço do local de armazenamento onde o objeto estará ou foi localizado pode ser usado, mas apenas de maneiras limitadas. [...] O programa tem comportamento indefinido se:
[...]
- o ponteiro é usado para acessar um membro de dados não estáticos ou chamar uma função de membro não estático do objeto , ou
No entanto, neste exemplo:
- o
()
operador do lambda é chamado enquanto a vida útil do lambda ainda é válida - É então suspenso,
- então a lambda é destruída,
- e, em seguida, a função de membro (operador
()
) é retomada em algum momento.
Essa retomada é considerada um comportamento indefinido?
c++
language-lawyer
c++20
c++-coroutine
Mike Lui
fonte
fonte
this
ponteiro é invalidada. Considere também a discussão nos comentários.Respostas:
[dcl.fct.def.coroutine] p3 :
O parâmetro implícito do objeto é, no seu exemplo, uma referência const e, portanto, essa referência ficará pendente quando a execução for retomada após a destruição do objeto de fechamento.
No entanto, na nota de objetos sendo destruídos durante a execução de uma função membro, isso é realmente bom por si só, e nada além do próprio padrão implica isso em [basic] :
(NB: o UB acima é porque o implícito
this
não é lavado e ainda se refere ao parâmetro implícito do objeto.)Portanto, seu exemplo parece estar bem definido, dependendo da idéia de que a retomada da execução não se enquadre nas mesmas regras que uma invocação original. Observe que a referência ao objeto de fechamento pode estar pendente, mas não é acessada de forma alguma entre a suspensão e a retomada.
fonte