Pergunta

O que é std::pair para, por que eu iria usá-lo, e quais os benefícios que faz boost::compressed_pair trazer?

Foi útil?

Solução

std::pair é um tipo de dados para o agrupamento de dois valores em conjunto como uma única objeto. std::map usa-lo para a chave, pares de valores.

Enquanto você está aprendendo pair , você pode verificar tuple . É como pair mas para agrupar um número arbitrário de valores. tuple faz parte do TR1 e muitos compiladores já incluí-lo com suas implementações de biblioteca padrão.

Além disso, check-out Capítulo 1, "Tuples", do livro As C ++ padrão biblioteca de extensões: Um Tutorial e Referência por Pete Becker, ISBN-13:. 9780321412997, para uma explicação completa

text alt

Outras dicas

compressed_pair usa alguns truques modelo para economizar espaço. Em C ++, um objecto (pequeno o) não podem ter o mesmo endereço como um objecto diferente.

Assim, mesmo se você tiver

struct A { };

tamanho do A não vai ser 0, porque então:

A a1;
A a2;
&a1 == &a2;

iria realizar, o que não é permitido.

e muitos compiladores vai fazer o que é chamado de "otimização de classe base vazia":

struct A { };
struct B { int x; };
struct C : public A { int x; };

Aqui, é bom para B e C ter o mesmo tamanho, mesmo se sizeof(A) não pode ser zero.

Assim boost::compressed_pair aproveita essa otimização e vontade, sempre que possível, herdar de um ou outro dos tipos do par se ela estiver vazia.

Assim, um std::pair pode parecer (eu elidido um bom negócio, ctors etc.):

template<typename FirstType, typename SecondType>
struct pair {
   FirstType first;
   SecondType second;
};

Isso significa que se quer FirstType ou SecondType é A, seu pair<A, int> tem que ser maior do que sizeof(int).

Mas se você usar compressed_pair, seu código gerado ficará semelhante a:

 struct compressed_pair<A,int> : private A {
    int second_;
    A first() { return *this; }
    int second() { return second_; }
 };

E compressed_pair<A,int> só será tão grande como sizeof (int).

Às vezes você precisa de retornar 2 valores de uma função, e muitas vezes é um exagero para ir e criar uma classe só para isso.

std:. Par vem a calhar nesses casos

Eu acho impulso: compressed_pair é capaz de otimizar afastado os membros de tamanho 0. Que é útil principalmente para máquinas modelo pesado em bibliotecas.

Se você controlar os tipos diretamente, é irrelevante.

Pode soar estranho ouvir que se preocupa compressed_pair cerca de um par de bytes. Mas ele pode realmente ser importante quando se considera que compressed_pair pode ser usado. Por exemplo, vamos considerar este código:

boost::function<void(int)> f(boost::bind(&f, _1));

Ele pode de repente ter um grande impacto para uso compressed_pair em casos como o acima. O que poderia acontecer se a impulsionar :: bind armazena o ponteiro de função ea _1 place-holder como membros em si mesmo ou em um std::pair em si mesmo? Bem, poderia inchar até sizeof(&f) + sizeof(_1). Assumindo um ponteiro de função tem 8 bytes (não é incomum especialmente para funções membro) e o marcador tem um byte (ver a resposta de Logan para porquê), em seguida, que se poderia necessário 9 bytes para o objecto de ligação. Por causa de alinhamento, isto poderia inchar até 12 bytes de um sistema de 32 bits habitual.

boost::function incentiva suas implementações para aplicar uma pequena otimização objeto. Isso significa que para pequena functors, um pequeno tampão incorporado diretamente no objeto boost::function é usado para armazenar o functor. Para functors maiores, a pilha teria que ser usado usando novo operador para obter memória. Por volta de impulsionar versão 1.34 , foi decidido adoptar essa otimização , porque foi uma figurado poderia ganhar alguns muito grandes benefícios de desempenho.

Agora, um razoável (ainda, talvez ainda bastante pequena) limite para um pequeno tampão como seria de 8 bytes. Ou seja, nosso objeto ligamento bastante simples seria não apto para o pequeno buffer, e exigiria operador de novo a ser armazenado. Se o objecto se ligam acima usaria uma compressed_pair, pode efectivamente reduzir o seu tamanho de 8 bytes (ou 4 bytes de ponteiro não membro função vezes), porque o marcador é nada mais do que um objecto vazio.

Então, o que pode parecer apenas desperdiçando um monte de pensamento para apenas apenas alguns bytes na verdade pode ter um impacto significativo no desempenho.

É classe padrão para armazenar um par de valores. É retornou / utilizada por algumas funções padrão, como std::map::insert.

reivindicações boost::compressed_pair para ser mais eficiente: ver aqui

std :: pair vem a calhar para um par de outras classes de contêineres no STL.

Por exemplo:

std::map<>
std::multimap<> 

Ambos loja std :: pares de chaves e valores.

Ao usar o mapa e multimap, muitas vezes você acessar os elementos usando um ponteiro para um par.

Informações adicionais: boost :: compressed_pair é útil quando um dos tipos do par é um struct vazio. Isto é frequentemente usado no modelo metaprogramming quando tipos do par são programaticamente inferida a partir de outros tipos. No final, em seguida, você geralmente tem alguma forma de "estrutura vazia".

Eu preferiria std :: pair por qualquer uso "normal", a menos que você estiver em modelo metaprogramming pesado.

Não é nada, mas uma estrutura com duas variáveis ??sob o capô.

Na verdade, eu não gosto de usar std :: pair em função retorna. O leitor do código teria de saber o que .primeira é eo que .segunda é.

O compromisso que eu uso às vezes é criar imediatamente constantes referências ao .primeira e .segunda, enquanto nomeando as referências claramente.

O que é std :: pair para, por que eu iria usá-lo?

É tão simples de dois elementos tupla. Ele foi definido na primeira versão de STL em momentos em que compiladores não foram amplamente apoiar modelos e técnicas de metaprogramação que seriam necessários para implementar tipo mais sofisticado de tupla como Boost.Tuple .

É útil em muitas situações. std::pair é usado em recipientes associativos padrão. Ele pode ser utilizado como uma forma simples de std::pair<iterator, iterator> intervalo - por isso pode-se definir algoritmos aceitando único objecto representando a gama, em vez de dois iterators separadamente. (É uma alternativa útil em muitas situações.)

Às vezes, há dois pedaços de informação que você acabou de passar sempre por aí juntos, seja como um parâmetro, ou um valor de retorno, ou o que quer. Claro, você pode escrever seu próprio objeto, mas se é apenas dois pequenos primitivos ou semelhante, por vezes, um par parece muito bem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top