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

questionAnswers(2)

yourAnswerToTheQuestion