Pode `* this` ser` move () `d?
Eu gostaria de definir uma classe para organizar dados; quando o empacotamento terminar, eu gostaria demove
os dados do empacotamento de fora dele, o que provavelmente invalidará o objeto de empacotamento.
Eu acredito que isso é possível com ostatic
funçãoextractData
abaixo:
class Marshaller
{
public:
static DataType extractData(Marshaller&& marshaller)
{
return std::move(marshaller.data);
}
private:
DataType data;
}
Isso é um pouco inconveniente de chamar, no entanto:
Marshaller marshaller;
// ... do some marshalling...
DataType marshalled_data{Marshaller::extractData(std::move(marshaller))};
Então, posso envolvê-lo com uma função de membro?
DataType Marshaller::toDataType()
{
return Marshaller::extractData(std::move(*this));
}
Obviamente, isso seria chamado usando:
DataType marshalled_data{marshaller.toDataType()};
... que, para mim, parece muito melhor. Mas issostd::move(*this)
coisa parece muito suspeita. No contexto da chamada paratoDataType()
, marshaller
não pode ser usado novamente, mas acho que o compilador não pode saber disso: o corpo da função pode estar fora da unidade de compilação do chamador, portanto, não há nada para indicar quemarshaller
tevemove()
aplicado a ele.
Esse comportamento é indefinido? Está perfeitamente bem? Ou em algum lugar no meio? Existe uma maneira melhor de atingir o mesmo objetivo, de preferência sem usar uma macro ou exigir que o chamador expliquemove
marshaller
?
EDITAR: Com o G ++ e o Clang ++, descobri que não apenas eu poderia compilar o caso de uso acima, mas também poderiacontinuar a fazer modificações nos dados subjacentes por meio do empacotadore extraia novamente os dados modificados usando o métodotoDataType
função. Eu também descobri que ojá extraído dados emmarshalled_data
continuou a ser alterado pormarshaller
, o que indica que omarshalled_data
é compartilhado entre omarshaller
e o contexto de chamada, então suspeito que haja um vazamento de memória ou um comportamento indefinido (da exclusão dupla) aqui.
EDIT 2: Se eu colocar uma declaração de impressão emDataType
destruidor de, pareceduas vezes quando o chamador sai do escopo. Se eu incluir um membro de dados emDataType
que possui uma matriz, com um correspondentenew[]
edelete[]
Eu recebo umglibc
erro "duplo livre ou corrompido". Então, eu não tenho certeza de como issopoderia esteja seguro, mesmo que várias respostas tenham dito que é tecnicamente permitido. Uma resposta completa deve explicar o que é necessário para usar esta técnica corretamente com um método não trivial.DataType
classe.
EDIT 3: Isso é o suficiente de uma toca de coelho / lata de vermes que eu abrioutra pergunta para resolver minhas preocupações remanescentes.