Skip to content
Menu
CDhistory
CDhistory

Move constructors

Posted on Maio 26, 2021 by admin

Um move constructor da classe T é um constructor sem modelo cujo primeiro parâmetro é T&&, const T&&, volatile T&&, ou const volatile T&&, e ou não há outros parâmetros, ou o resto dos parâmetros todos têm valores padrão.

>

  • Conteúdo
  • Sintaxe
  • Explicação
  • Construtor de movimento implícito
  • Construtor de movimento implicitamente declarado excluído
  • Construtor de movimento trivial
  • Construtor de movimento elegível
  • Construtor de movimento implícito
  • Notas
  • Exemplo
  • Relatórios de defeitos
  • Ver também

Conteúdo

  • 1 Sintaxe
  • 2 Explicação
  • 3 Construtor de movimento implícito
  • 4 Construtor de movimento implícito
  • 5 Construtor de movimento trivial
  • 6 Construtor de movimento elegível
  • 7 Implicitamente-construtor de movimento definido
  • 8 Notas
  • 9 Exemplo
  • 10 Relatórios de defeitos
  • 11 Veja também

Sintaxe

nome_da_classe ( class_name && ) (1) (desde C++11)
nome_da_classe ( class_name && ) = padrão; (2) (desde C++11)
class_name ( class_name && ) = apagar; (3) (desde C++11)

Onde class_name deve nomear a classe atual (ou a instanciação atual de um template de classe), ou, quando declarado no namespace scope ou em uma declaração de amigo, deve ser um nome de classe qualificado.

Explicação

1) Declaração típica de um construtor move.
2) Forçando um construtor move a ser gerado pelo compilador.
3) Evitando construtor move implícito.

O construtor move é normalmente chamado quando um objeto é inicializado (por inicialização direta ou por cópia-inicialização) a partir de rvalue (xvalue ou prvalue) (até C++17)xvalue (desde C+++17) do mesmo tipo, incluindo

  • inicialização: T a = std::move(b); ou T a(std::move(b));, onde b é do tipo T;
  • argumento da função passando: f(std::move(a)));, onde a é do tipo T e f é nulo f(T t);
  • function return: return a; dentro de uma função como T f(), onde a é do tipo T que tem um construtor de movimento.

Quando o inicializador é um prvalue, a chamada construtor de movimento é frequentemente optimizada para fora (até C++17)nunca feita (desde C++17), veja copy elision.

Mover construtores tipicamente “roubam” os recursos detidos pelo argumento (e.g. apontadores para objetos alocados dinamicamente, descritores de arquivos, soquetes TCP, fluxos I/O, threads em execução, etc.) ao invés de fazer cópias deles, e deixar o argumento em algum estado válido, mas indeterminado. Por exemplo, mover-se de um std::string ou de um std::vector pode resultar em deixar o argumento vazio. No entanto, este comportamento não deve ser confiado. Para alguns tipos, tais como std::unique_ptr, o estado movido de um estado é totalmente especificado.

Construtor de movimento implícito

Se nenhum construtor de movimento definido pelo usuário for fornecido para um tipo de classe (struct, class, ou union), e tudo o que se segue é verdade:

  • não há construtores de cópia declarados pelo usuário;
  • não há operadores de atribuição de cópia declarados pelo usuário;
  • não há operadores de atribuição de movimento declarados pelo usuário;
  • não há destrutor declarado pelo usuário.

então o compilador irá declarar um construtor de mudanças como não explícito inline public membro da sua classe com a assinatura T::T(T&&).

Uma classe pode ter construtores move múltiplos, por exemplo, tanto T::T(const T&&) como T::T(T&&). Se alguns construtores de movimento definidos pelo usuário estiverem presentes, o usuário ainda pode forçar a geração do construtor de movimento implicitamente declarado com a palavra-chave default.

O construtor de movimento implicitamente declarado (ou declarado por padrão em sua primeira declaração) tem uma especificação de exceção como descrita na especificação de exceção dinâmica (até C++17)especificação de exceção (desde C++17)

Construtor de movimento implicitamente declarado excluído

O construtor de movimento implicitamente declarado ou declarado por padrão para a classe T é definido como excluído se alguma das seguintes opções for verdadeira:

  • T possui membros de dados não estáticos que não podem ser movidos (possui construtores de movimentos excluídos, inacessíveis ou ambíguos);
  • T possui uma classe base direta ou virtual que não pode ser movida (possui construtores de movimentos excluídos, inacessíveis ou ambíguos);
  • T tem uma classe base direta ou virtual com um destruidor excluído ou inacessível;
  • T é uma classe tipo união e tem um membro variante com construtor de mudanças não trivial.

Um construtor de movimento padrão que é excluído é ignorado por resolução de sobrecarga (caso contrário, isso impediria a inicialização da cópia de valor).

Construtor de movimento trivial

O construtor de movimento para a classe T é trivial se tudo o que se segue for verdade:

  • não é fornecido pelo usuário (ou seja, é implicitamente definido ou padrão);
  • T não tem funções de membro virtual;
  • T não tem classes base virtuais;
  • o construtor move selecionado para cada base direta de T é trivial;
  • o construtor move selecionado para cada tipo de classe não-estática (ou array do tipo de classe) membro de T é trivial.

Um construtor move trivial é um construtor que executa a mesma ação que o construtor copy trivial, ou seja, faz uma cópia da representação do objeto como se fosse por std::memmove. Todos os tipos de dados compatíveis com a linguagem C (tipos POD) são trivialmente móveis.

Construtor de movimento elegível

Um construtor de movimento é elegível se não for excluído.

(até C++20)

Um construtor de mudanças é elegível se

  • não for apagado, e
  • suas restrições associadas, se houver, forem satisfeitas, e
  • nenhum construtor de mudanças com o mesmo primeiro tipo de parâmetro é mais restrito do que ele.
(desde C+++20)

A trivialidade dos construtores move elegíveis determina se a classe é um tipo de vida implícita, e se a classe é um tipo trivialmente copiável.

Construtor de movimento implícito

Se o construtor de movimento implícito não for excluído ou trivial, ele é definido (ou seja, um corpo de função é gerado e compilado) pelo compilador se odr-usado ou necessário para avaliação constante. Para tipos de união, o construtor de movimentos implicitamente definido copia a representação do objeto (como por std::memmove). Para tipos de classes não-unionais (classe e estrutura), o construtor de movimentações executa movimentações de membros completos das bases do objeto e membros não-estáticos, em sua ordem de inicialização, usando inicialização direta com um argumento xvalue. Se isto satisfaz os requisitos de um construtor constexpr, o construtor move gerado é constexpr.

Notas

Para tornar possível a garantia de exceção forte, construtores move definidos pelo usuário não devem lançar exceções. Por exemplo, std::vector depende de std::move_if_noexcepção para escolher entre mover e copiar quando os elementos precisam ser realocados.

Se ambos os construtores copy e move são fornecidos e nenhum outro construtor é viável, a resolução de sobrecarga seleciona o construtor move se o argumento for um valor do mesmo tipo (um valor x como o resultado de std::move ou um prvalue como um temporário sem nome (até C++17)), e seleciona o construtor copy se o argumento for um valor l (objeto nomeado ou uma função/operador retornando referência lvalue). Se apenas o construtor de cópia é fornecido, todas as categorias de argumento o selecionam (desde que leve uma referência para const, uma vez que os valores podem ser vinculados a referências const), o que faz com que a cópia de segurança para mover, quando mover não esteja disponível.

Um construtor é chamado de ‘move constructor’ quando leva uma referência rvalue como parâmetro. Não é obrigatório mover nada, a classe não é obrigada a ter um recurso a ser movido e um ‘construtor move’ pode não ser capaz de mover um recurso como no caso permitido (mas talvez não sensato) onde o parâmetro é uma referência de valor constante (const T&&).

Exemplo

Executar este código
#include <string>#include <iostream>#include <iomanip>#include <utility> struct A{ std::string s; int k; A() : s("test"), k(-1) { } A(const A& o) : s(o.s), k(o.k) { std::cout << "move failed!\n"; } A(A&& o) noexcept : s(std::move(o.s)), // explicit move of a member of class type k(std::exchange(o.k, 0)) // explicit move of a member of non-class type { }}; A f(A a){ return a;} struct B : A{ std::string s2; int n; // implicit move constructor B::(B&&) // calls A's move constructor // calls s2's move constructor // and makes a bitwise copy of n}; struct C : B{ ~C() { } // destructor prevents implicit move constructor C::(C&&)}; struct D : B{ D() { } ~D() { } // destructor would prevent implicit move constructor D::(D&&) D(D&&) = default; // forces a move constructor anyway}; int main(){ std::cout << "Trying to move A\n"; A a1 = f(A()); // return by value move-constructs the target from the function parameter std::cout << "Before move, a1.s = " << std::quoted(a1.s) << " a1.k = " << a1.k << '\n'; A a2 = std::move(a1); // move-constructs from xvalue std::cout << "After move, a1.s = " << std::quoted(a1.s) << " a1.k = " << a1.k << '\n'; std::cout << "Trying to move B\n"; B b1; std::cout << "Before move, b1.s = " << std::quoted(b1.s) << "\n"; B b2 = std::move(b1); // calls implicit move constructor std::cout << "After move, b1.s = " << std::quoted(b1.s) << "\n"; std::cout << "Trying to move C\n"; C c1; C c2 = std::move(c1); // calls copy constructor std::cout << "Trying to move D\n"; D d1; D d2 = std::move(d1);}

>

Output:

Trying to move ABefore move, a1.s = "test" a1.k = -1After move, a1.s = "" a1.k = 0Trying to move BBefore move, b1.s = "test"After move, b1.s = ""Trying to move Cmove failed!Trying to move D

Relatórios de defeitos

Os seguintes relatórios de defeitos com mudança de comportamento foram aplicados retroativamente aos padrões C++ publicados anteriormente.

DR Aplicado a Comportamento como publicado Comportamento correto
CWG 1402 C+++11 um construtor de movimento padrão que
chamaria um construtor de cópia não trivial foi excluído;
um construtor de movimento padrão que é excluído
continua participando da resolução de sobrecarga
permite a chamada a esse construtor de cópia;
sempre ignorado na resolução de sobrecarga
CWG 2094> C++11 um subobjecto volátil feito de um padrão
mova construtor nãotrivial (CWG496)
trivialidade não afectada

Ver também

  • construtor de conversão
  • atribuição de cópia
  • construtor de cópia
  • elisão de cópia
  • construtor padrão
  • destrutor
  • explícito
  • inicialização
    • inicialização agregada
    • inicialização constante
    • inicialização de cópia
    • inicialização padrão
    • inicialização direta
    • lista de inicializadores
    • inicialização de lista
    • inicialização de referência
    • inicialização de valor
    • inicialização de valor
    • inicialização zero
  • atribuição de movimento
  • novo

Deixe uma resposta Cancelar resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

Artigos recentes

  • Acela está de volta: NYC ou Boston por $99
  • Entrada OMIM – # 608363 – CHROMOSOME 22q11.2 SÍNDROME DE DUPLICAÇÃO
  • Kate Albrecht’s Parents – Learn More About Her Father Chris Albrecht And Mother Annie Albrecht
  • Temple Fork Outfitters
  • Burr (romance)

Arquivo

  • Fevereiro 2022
  • Janeiro 2022
  • Dezembro 2021
  • Novembro 2021
  • Outubro 2021
  • Setembro 2021
  • Agosto 2021
  • Julho 2021
  • Junho 2021
  • Maio 2021
  • Abril 2021
  • DeutschDeutsch
  • NederlandsNederlands
  • SvenskaSvenska
  • DanskDansk
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • RomânăRomână
  • PolskiPolski
  • ČeštinaČeština
  • MagyarMagyar
  • SuomiSuomi
  • 日本語日本語
©2022 CDhistory | Powered by WordPress & Superb Themes