Há algum ponto para definir objetos movidos apenas em C++11?
class B {
const string objName;
public:
B ( B && ) = default;
B & operator= ( B && ) = default;
B ( const B & ) = delete;
B & operator= ( const B & ) = delete;
B(const string & name) :
objName(name) {
}
virtual ~B();
const string name() const { return objName;};
}
e eu chamei B por estas linhas:
class A {
A(){}
void take(B b);
}
A a;
B b("test");
cout<<b.name();
a.take(std::move(b));
cout<<b.name();
As minhas perguntas:
- Mesmo que eu tenha faltado ao construtor de movimentos, Eu não posso escrever A. take(b) e estou recebendo erro de compilação. Compreendo que a copy constructor seja apagada, mas parece que a escolha lógica é usar o construtor de movimento quando está em falta sem necessidade de escrever std:: mover assim A. take (B)
- No resultado, o" teste " é impresso duas vezes. Por que o objeto b não foi removido depois de chamar o movimento? Se o objecto b ainda existir e uma cópia dele tiver sido enviada para o A. take(mover(B)), então significa que não temos qualquer uso do movimento para objectos rvalue.
- é uma boa prática usar objetos apenas em movimento como acima (remover o construtor de cópia e Operador de atribuição e construtor de movimento em falta e mover missão)?
2 answers
class B {
std::string objName;
public:
B ( B && ) = default;
B & operator= ( B && ) = default;
B ( const B & ) = delete;
B & operator= ( const B & ) = delete;
B(const std::string & name) :
objName(name) {}
virtual ~B() {}
std::string name() const { return objName;}
};
class A {
public:
std::vector<B> v;
void take(B && b)
{
v.push_back(std::move(b));
}
};
int main()
{
A a;
B b("test");
std::cout << "Before: " << b.name() << std::endl;
a.take(std::move(b));
std::cout << "After: " << b.name() << std::endl;
std::cout << "A has elements: " << std::endl;
for(B &b : a.v)
std::cout << " " << b.name() << std::endl;
}
Estás a aceder a um valor que foi transferido, o que não faz sentido nenhum! esta resposta {[8] } já faz um bom trabalho de explicar, mas abaixo eu também incluí texto de a STL reference for std:: move.
Http://en.cppreference.com/w/cpp/utility/move
Encontrei dois usos legítimos na minha experiência. Em ambos os casos a mudança-apenas os objetos controlavam um recurso físico que se compartilhado por dois objetos quebraria tudo.Salvo indicação em contrário, todos os objectos normais de biblioteca que tenham foi movido de são colocados em um estado válido, mas não especificado. Isto é ... , apenas as funções sem pré-condições, como a atribuição operador, pode ser usado com segurança no objeto depois que ele foi movido.
Um exemplo é uma classe de 'Socket':
1) você quer dar um construtor padrão para o Socket "vazio" que ainda não recebeu nenhum IP ou porto.
2) você quer dar um construtor que recebe um IP e porta. após a construção, o 'Socket' irá tentar ligar-se e poderá abrir uma excepção se a ligação falhar
3) a coisa óbvia é o destruidor - desligará o objecto e libertará todos os recursos do sistema subjacente que este objecto possa deter.
digamos que tenho uma função que cria uma tomada e devolve-a. Se eu ligar para o construtor de cópias isso significa que:
o novo socket copiado (return value) tentará conectar-se ao mesmo IP e porta a que o socket de origem foi conectado. isso pode não ser possível.
o 'socket' de origem será desligado e destruído
É possível que tentar copiar o socket só crie uma enorme confusão. pelo contrário, um construtor de movimentos resolve esta massa com cuidado:
o valor de retorno recebe todos os recursos operacionais subjacentes sem desconectá-los ou destruí-los.
o soquete de origem fica vazio e o destruidor não tem nada para desligar ou destruir.
Parece que os 'sockets' provavelmente só seriam movidos, não copiados.
Isto pode aplicar-se a Classe "processo" - se eu tentar retornar um processo copiando, eu poderia tentar abrir o mesmo processo novamente, apenas para desligar o original. uma confusão! ao mover o processo, não o faço. Eu simplesmente movo o processo de uma função para outra.