Minha pergunta é simples: os elementos std :: vector são garantidamente contíguos? Em resumo, posso usar o ponteiro para o primeiro elemento de um std :: vector como um C-array?
Se não me falha a memória, o padrão C ++ não oferecia tal garantia. No entanto, os requisitos std :: vector eram tais que era virtualmente impossível atendê-los se os elementos não fossem contíguos.
Alguém pode esclarecer isso?
Exemplo:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
values
dentro daqueleif
bloco. Não sei a resposta para sua pergunta, entretanto, estou apenas deixando um comentário. :)values
, especificamente aquelas que mudam seu tamanho (por exemplo,push_back()
), podem solicitar uma realocação do vetor subjacente que invalida o ponteiro para o qual foi copiadoarray
. É o mesmo princípio por trás do uso de um vector :: iterator em vez de um ponteiro para o vetor. :)Respostas:
Isso foi omitido no padrão C ++ 98 propriamente dito, mas posteriormente adicionado como parte de um TR. O próximo padrão C ++ 0x irá obviamente conter isso como um requisito.
De n2798 (rascunho de C ++ 0x):
fonte
std::vector
que são contíguas. Ex .: emstd::vector<std::vector<int>> v
elementosv[0]
,v[1]
... são armazenadas posteriormente na memória, mas o elementov[0].back()
ev[1].front()
não são garantidos para ser.Como outras respostas indicaram, o conteúdo de um vetor é garantidamente contínuo (exceto pela estranheza de bool).
O comentário que eu queria adicionar é que se você fizer uma inserção ou exclusão no vetor, o que poderia fazer com que o vetor realocasse sua memória, você fará com que todos os seus ponteiros e iteradores salvos sejam invalidados.
fonte
O padrão de fato garante que a
vector
seja contínuo na memória e que&a[0]
possa ser passado para umaC
função que espera um array.A exceção a esta regra é
vector<bool>
que usa apenas um bit por,bool
portanto, embora tenha memória contínua, ela não pode ser usada como umbool*
(isso é amplamente considerado uma otimização falsa e um erro).BTW, por que você não usa iteradores? É para isso que servem.
fonte
Como outros já disseram,
vector
internamente usa uma matriz contígua de objetos. Os ponteiros para essa matriz devem ser tratados como inválidos sempre que qualquer função de membro não const for chamada de IIRC.Contudo, há uma exceção!!
vector<bool>
possui uma implementação especializada projetada para economizar espaço, de forma que cada bool use apenas um bit. A matriz subjacente não é uma matriz contígua de bool e a aritmética da matrizvector<bool>
não funciona comovector<T>
faria.(Suponho que também seja possível que isso seja verdade para qualquer especialização de vetor, uma vez que sempre podemos implementar uma nova. No entanto,
std::vector<bool>
é a única, err, especialização padrão em que a aritmética de ponteiro simples não funciona.)fonte
std::vector
e todos os outros vetores são obrigados a usar o armazenamento contíguo. Portanto,std::vector<bool>
é (felizmente) o único vetor padrão que é estranho. (Acredito fortemente que esta especialização deve ser descontinuada e substituída, por exemplo, por umstd::dynamic_bitset
com praticamente a mesma funcionalidade. Não é uma estrutura de dados ruim, apenas não é um vetor.)Eu encontrei esse segmento porque tenho um caso de uso em que vetores que usam memória contígua são uma vantagem.
Estou aprendendo a usar objetos de buffer de vértice em OpenGL. Eu criei uma classe de wrapper para conter a lógica do buffer, então tudo que preciso fazer é passar uma matriz de floats e alguns valores de configuração para criar o buffer. Quero ser capaz de gerar um buffer a partir de uma função com base na entrada do usuário, portanto, o comprimento não é conhecido no momento da compilação. Fazer algo assim seria a solução mais fácil:
Agora posso passar os flutuadores do vetor como um array para as funções relacionadas ao buffer do OpenGL. Isso também elimina a necessidade de sizeof para determinar o comprimento da matriz.
Isso é muito melhor do que alocar um grande array para armazenar os floats e esperar que eu o torne grande o suficiente, ou fazer meu próprio array dinâmico com armazenamento contíguo.
fonte
v
ao invés dev
si mesmo? porque passarv
sozinho fará com que uma cópia seja feita dentro da função, que deixará de existir após o término da função. Portanto, você está empurrando algo para o vetor apenas para excluí-lo quando a função terminar.cplusplus.com:
fonte
Sim, os elementos de um std :: vector são garantidamente contíguos.
fonte