Eu já vi default
usado ao lado de declarações de função em uma classe. O que isso faz?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Eu já vi default
usado ao lado de declarações de função em uma classe. O que isso faz?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Respostas:
É um novo recurso do C ++ 11 .
Isso significa que você deseja usar a versão gerada pelo compilador dessa função, para não precisar especificar um corpo.
Você também pode usar = delete
para especificar que não deseja que o compilador gere essa função automaticamente.
Com a introdução de construtores de movimentação e operadores de atribuição de movimentação, as regras para quando versões automáticas de construtores, destruidores e operadores de atribuição são geradas se tornaram bastante complexas. Usar = default
e = delete
facilitar as coisas, pois você não precisa se lembrar das regras: basta dizer o que deseja que aconteça.
= delete
é mais forte: significa que é proibido usar essa função, embora ela ainda participe da resolução de sobrecarga.
Este é um novo recurso C ++ 0x que informa ao compilador para criar a versão padrão do respectivo construtor ou operador de atribuição, ou seja, aquele que apenas executa a ação de copiar ou mover para cada membro. Isso é útil porque o construtor de movimentação nem sempre é gerado por padrão (por exemplo, se você tem um destruidor personalizado), diferentemente do construtor de cópia (e da mesma forma para a atribuição), mas se não houver nada não trivial para escrever, é melhor deixar o compilador lidar com isso do que soletrar você mesmo a cada vez.
Observe também que um construtor padrão não seria gerado se você fornecer outro construtor não padrão. Se você ainda deseja o construtor padrão também, pode usar esta sintaxe para que o compilador faça um.
Como outro caso de uso, há várias situações nas quais um construtor de cópias não seria gerado implicitamente (por exemplo, se você fornecer um construtor de movimentação personalizado). Se você ainda deseja a versão padrão, pode solicitá-la com esta sintaxe.
Consulte a Seção 12.8 da norma para obter detalhes.
operator new/new[]
, operator delete/delete[]
e suas sobrecargas.
É novo no C ++ 11, veja aqui . Pode ser bastante útil se você definiu um construtor, mas deseja usar padrões para os outros. Antes do C ++ 11, você teria que definir todos os construtores depois de definir um, mesmo que sejam equivalentes aos padrões.
Observe também que, em determinadas situações, é impossível fornecer um construtor padrão definido pelo usuário que se comporte da mesma forma que o compilador sintetizou um na inicialização padrão e no valor . default
permite recuperar esse comportamento.
Rascunho padrão C ++ 17 N4659
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Funções explicitamente padronizadas":
1 Uma definição de função do formulário:
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
é chamada de definição explicitamente padronizada. Uma função explicitamente inadimplente deve
(1.1) - ser uma função membro especial,
(1.2) - tem o mesmo tipo de função declarada (exceto para possíveis qualificadores ref diferentes e exceto que, no caso de um construtor de cópias ou operador de atribuição de cópias, o tipo de parâmetro pode ser "referência a não-const T", onde T é o nome da classe da função membro) como se tivesse sido implicitamente declarado, e
(1.3) - não possui argumentos padrão.
2 Uma função explicitamente padronizada que não é definida como excluída pode ser declarada constexpr apenas se tivesse sido implicitamente declarada como constexpr. Se uma função é explicitamente padronizada em sua primeira declaração, ela é considerada implicitamente constexpr se a declaração implícita for.
3 Se uma função explicitamente padronizada for declarada com um noexcept-specifier que não produz a mesma especificação de exceção que a declaração implícita (18.4), então
(3.1) - se a função for explicitamente padronizada em sua primeira declaração, ela será definida como excluída;
(3.2) - caso contrário, o programa está mal formado.
4 [Exemplo:
struct S { constexpr S() = default; // ill-formed: implicit S() is not constexpr S(int a = 0) = default; // ill-formed: default argument void operator=(const S&) = default; // ill-formed: non-matching return type ~ S() noexcept(false) = default; // deleted: exception specification does not match private: int i; // OK: private copy constructor S(S&); }; S::S(S&) = default; // OK: defines copy constructor
- exemplo final]
5 Funções explicitamente padronizadas e funções declaradas implicitamente são chamadas coletivamente de funções padrão, e a implementação deve fornecer definições implícitas para elas (15.1 15.4, 15.8), o que pode significar defini-las como excluídas. Uma função é fornecida pelo usuário se for declarada pelo usuário e não for explicitamente padronizada ou excluída em sua primeira declaração. Uma função explicitamente padronizada fornecida pelo usuário (ou seja, explicitamente padronizada após sua primeira declaração) é definida no ponto em que é explicitamente padronizada; se tal função estiver implicitamente definida como excluída, o programa será mal formado. [Nota: Declarar uma função como padrão após sua primeira declaração pode fornecer execução eficiente e definição concisa enquanto permite uma interface binária estável para uma base de código em evolução. - nota final]
6 [Exemplo:
struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~ trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration
- exemplo final]
É claro que a questão é quais funções podem ser declaradas implicitamente e quando isso acontece, que expliquei em: