Tipos de valor (C++ moderno)
As classes de C++ são por padrão tipos de valor.Este tópico fornece uma visão geral sobre introdutórias de tipos de valor e os problemas em relação ao seu uso.
Valor CONTRA. tipos de referência
Conforme observado anteriormente, as classes C++ são por padrão tipos de valor.Podem ser especificados como tipos de referência, que permitem o comportamento polimorfo para oferecer suporte a programação orientada a objeto.Tipos de valor são exibidos em vez da perspectiva de controle de memória e de layout, enquanto os tipos de referência são sobre classes base e funções virtuais para fins polimórficas.Por padrão, os tipos de valor são copyable, que significa que há sempre um construtor de impressão e um operador de atribuição de impressão.Para tipos de referência, você faz a classe non-copyable (desativar o construtor de impressão e o operador de atribuição de impressão) e usa um destrutor virtual, que suporta o polimorfismo esperado.Tipos de valor são também sobre o conteúdo, que, quando são copiados, oferecem sempre dois valores independentes que podem ser alterados separadamente.Tipos de referência são sobre a identidade – tipo de objeto que ele é?Por esse motivo, “os tipos” referência também são referidos como “tipos polimórficas”.
Se você realmente deseja da como o tipo (a classe base, funções virtuais), você precisa explicitamente desativar copiar, conforme mostrado na classe de MyRefType no código a seguir.
// cl /EHsc /nologo /W4
class MyRefType {
private:
MyRefType & operator=(const MyRefType &);
MyRefType(const MyRefType &);
public:
MyRefType () {}
};
int main()
{
MyRefType Data1, Data2;
// ...
Data1 = Data2;
}
Compile o código anterior resultará ao seguinte erro:
Tipos de valor e eficiência de animação
A sobrecarga de alocação de impressão é impedida devido às novas otimizações de impressão.Por exemplo, quando você insere uma cadeia de caracteres no meio de um vetor de cadeias de caracteres, não haverá sobrecarga de realocação de impressão, somente um movimento mesmo que resulta em um vetor de crescimento próprio.Isso também se aplica a outras operações por exemplo, executando uma operação adicionar em dois objetos muito grandes.Como você ativar essas otimizações da operação de valor?Em alguns compiladores de C++, o compilador para isso permitirá que você implicitamente, bem como construtores de impressão pode ser automaticamente gerado pelo compilador.No entanto, Visual C++, sua classe necessário optar- “em” de mover a atribuição e construtores de declaração na sua definição de classe.Isso é feito usando a referência de vezes rvalue ampersand () && nas declarações de função de membro apropriados e definindo métodos de construtor de animação e da atribuição de animação.Você também precisa inserir o código correto “rouba a entranhas” fora do objeto de origem.
Como você decidir se você precisar mova ativado?Se você souber você ainda precisa da compilação de impressão ativada, você provavelmente mova ativado se pode ser mais barato de uma cópia profunda.No entanto, se você souber você precisar de suporte de animação, não significa necessariamente que você deseja copiar ativada.Esses casos último é chamada de um tipo “ou” - somente.Um exemplo mais na biblioteca padrão é unique_ptr.Como uma nota lateral, auto_ptr antigo é substituído, e foi substituído por unique_ptr precisamente devido à falta de suporte a semântica de movimentação na versão anterior do C++.
Usando a semântica de movimentação você pode retorno-por- valor ou inserção-em- médio.O que é uma otimização de impressão.Há uma necessidade para a alocação da heap como uma solução alternativa.Considere o seguinte pseudocódigo:
#include <set>
#include <vector>
#include <string>
using namespace std;
//...
set<widget> LoadHugeData() {
set<widget> ret;
// ... load data from disk and populate ret
return ret;
}
//...
widgets = LoadHugeData(); // efficient, no deep copy
vector<string> v = IfIHadAMillionStrings();
v.insert( begin(v)+v.size()/2, "scott" ); // efficient, no deep copy-shuffle
v.insert( begin(v)+v.size()/2, "Andrei" ); // (just 1M ptr/len assignments)
//...
HugeMatrix operator+(const HugeMatrix& , const HugeMatrix& );
HugeMatrix operator+(const HugeMatrix& , HugeMatrix&&);
HugeMatrix operator+( HugeMatrix&&, const HugeMatrix& );
HugeMatrix operator+( HugeMatrix&&, HugeMatrix&&);
//...
hm5 = hm1+hm2+hm3+hm4+hm5; // efficient, no extra copies
Ativando mova para tipos de valor apropriado
Para valores como a classe onde o movimentação pode ser mais barato de uma cópia profunda, para ativar a compilação de animação e atribuição de mover para a eficiência.Considere o seguinte pseudocódigo:
#include <memory>
#include <stdexcept>
using namespace std;
// ...
class my_class {
unique_ptr<BigHugeData> data;
public:
my_class( my_class&& other ) // move construction
: data( move( other.data ) ) { }
my_class& operator=( my_class&& other ) // move assignment
{ data = move( other.data ); return *this; }
// ...
void method() { // check (if appropriate)
if( !data )
throw std::runtime_error("RUNTIME ERROR: Insufficient resources!");
}
};
Se você ativar a compilação/atribuição de impressão, também ativar a compilação/atribuição de movimentação se pode ser mais barata de uma cópia profunda.
Alguns tipos de valor não são mover somente, como quando você não pode clonar um recurso, simplesmente propriedade de transferência.Exemplo: unique_ptr.
Seção
Conteúdo
Consulte também
Conceitos
Sistema de tipo C++ (guia de programação do C++ moderno)