Pergunta

Por que é que o construtor único parâmetro de std::list<T> requer T para ser um tipo default-constructible? Quero dizer o seguinte código não compila.

struct Foo { // does not have default constructor.
  Foo (int i) {} 
}
int main(void) {
  std::list<Foo> l(10);
}

Parece possível usar a construção e destruir idiomas como eles já fizeram no std :: vector, embora com mais de manutenção de livro da classe de lista.

Em uma nota relacionada, porque não têm a função de capacidade na lista? Você pode argumentar que tal função um iria pagar o custo de alocação de memória up-front e eliminar a sobrecarga, mais tarde, como você push_back objetos. Pelo menos, fará com que as interfaces dos dois recipientes de sequência STL ligeiramente mais consistente.

Foi útil?

Solução

std :: lista não tem uma função de capacidade, porque não faz sentido; nunca tem que redimensionar como um vector faz. A sua capacidade é limitada apenas pela memória disponível, o que não é facilmente determinada.

A partir do que você pediu, eu acho que você realmente quer de reserva (). Isso é um one-off para o vetor porque (mal) precisa de um tal coisa; não há nenhuma exigência especial para fazer todas as funções consistente em todos os contêineres STL, especialmente quando eles fazem pouco sentido para os outros.

Você pode conseguir o mesmo efeito usando um alocador de costume. Como Manuel sugeriu, olhada impulso.

Outras dicas

Não há nenhuma exigência geral de que o tipo de ser constructible padrão - deve ser copiável e intransferível. Seu código não funciona porque você tentar criar uma lista de 10 itens - eles têm que ser construído de alguma forma e assim o construtor padrão deve ser usado - mas apenas neste caso específico. Se você criou uma lista vazia e adicionado a ele, não haveria tal exigência.

O mesmo é verdadeiro para outros recipientes - tentar compilar o seguinte:

#include <vector>

struct A {
    A( int x ) : z(x) {}
    int z;
};

std::vector <A> a(10);

Em relação à segunda parte da sua pergunta, eu tinha acabado de observar que a consistência da interface não foi um critério de projeto principal para os contentores normais - não há intenção, por exemplo, que um tipo de recipiente é um "drop-in "substituto para o outro. Há uma boa discussão deste nos itens 1 e 2 do livro de Scott Meyers' 'Effective STL'.

Neil já respondeu a pergunta principal .

Além disso, note que você precisa de um construtor padrão ao chamar de redimensionamento ().

Você pode contornar isso por ter uma lista STL de ponteiros para objetos, mas eu acho que isso já era óbvio para você.

Em uma nota relacionada, por que não ter o função de capacidade em lista? Você pode argumentar que tal função um pagaria custo de alocação de memória up-front e eliminar a sobrecarga, mais tarde, como você objetos push_back. Pelo menos ele vai tornar as interfaces de dois STL recipientes de sequência ligeiramente mais consistente.

Eu acho que o problema aqui é que listas STL permitir cross-list splicing . Se você deseja alocar antecipadamente memória, ter um olhar para o Impulsione Piscina Allocator .

A razão é que, ao construir uma lista de elementos n (em que n é o parâmetro que utilizado no construtor), a lista preenche a sua estrutura de n elementos com cópias de T ().

sgi documentação stl para lista .

Por que é que o único parâmetro construtor do std :: lista requer T para ser um tipo default-constructible?

Porque este contructor - cria lista com elementos (número que você passar como parâmetro). Valor de cada elemento será padrão. Além disso, você pode usar construtor com dois parâmetros, para criar uma lista com elementos que serão inicializados com o segundo valor do elemento.

Em uma nota relacionada, por que não ter o função de capacidade em lista?

Ele não tem sentido, porque o custo de adicionar novos elementos à lista é muito pouco do que no caso do vector.

std :: vector não tem um tal restrição. Minha pergunta é por que não utilizar as mesmas técnicas (Criar / destruir idiomas) no std :: lista também?

Não é restrição. Porque se você não usar tais construtor, inicializador padrão não será necessário. A mesma coisa vale para vetor.

Então, a pergunta é realmente "porque não têm funções de reserva e de capacidade na lista?"

A resposta para isso é que não há nenhuma razão para a memória de reserva com antecedência para lista - adicionar novos elementos nunca exige um realloc & cópia para elementos existentes, não há nenhuma exigência de que a memória segurando o conteúdo de uma lista ser contíguos, e iterators não fica invalidada quando se faz um list::push_back().

Todos esses são a razão para a existência de vector<>::reserve(), e ter memória em reserva para novos elementos é porque um vector<> irá realizar a colocação new na memória matéria.

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