Mi pregunta es simple: ¿se garantiza que los elementos std :: vector sean contiguos? En orden, ¿puedo usar el puntero al primer elemento de un std :: vector como una matriz C?
Si mi memoria no me sirve bien, el estándar C ++ no ofrecía tal garantía. Sin embargo, los requisitos de std :: vector eran tales que era prácticamente imposible cumplirlos si los elementos no eran contiguos.
¿Alguien puede aclarar esto?
Ejemplo:
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 de eseif
bloque. Sin embargo, no sé la respuesta a tu pregunta, así que solo dejo un comentario. :)values
, específicamente las que cambian su tamaño (por ejemplo,push_back()
), pueden provocar una reasignación del vector subyacente que invalida el puntero copiadoarray
. Es el mismo principio detrás del uso de un vector :: iterador en lugar de un puntero al vector. :)Respuestas:
Esto se omitió del estándar C ++ 98 propiamente dicho, pero luego se agregó como parte de un TR. El próximo estándar C ++ 0x, por supuesto, lo incluirá como requisito.
Desde n2798 (borrador de C ++ 0x):
fuente
std::vector
las contiguas. Ej .: enstd::vector<std::vector<int>> v
los elementosv[0]
,v[1]
, ... posteriormente se almacenan en la memoria, pero el elementov[0].back()
yv[1].front()
no se garantiza que sea.Como han señalado otras respuestas, se garantiza que el contenido de un vector sea continuo (excepto la rareza de bool).
El comentario que quería agregar es que si realiza una inserción o una eliminación en el vector, lo que podría hacer que el vector reasigne su memoria, entonces hará que todos sus punteros e iteradores guardados se invaliden.
fuente
De hecho, el estándar garantiza que a
vector
sea continuo en la memoria y que&a[0]
se pueda pasar a unaC
función que espera una matriz.La excepción a esta regla es
vector<bool>
que solo usa un bit porbool
, por lo tanto, aunque tiene memoria continua, no se puede usar comobool*
(esto se considera una optimización falsa y un error).Por cierto, ¿por qué no usas iteradores? Para eso son.
fuente
Como ya han dicho otros,
vector
utiliza internamente una matriz contigua de objetos. Los punteros en esa matriz deben tratarse como inválidos siempre que cualquier función miembro no constante se llame IIRC.¡¡Como sea, hay una excepción!!
vector<bool>
tiene una implementación especializada diseñada para ahorrar espacio, de modo que cada bool solo usa un bit. La matriz subyacente no es una matriz contigua de bool y la aritmética de matrizvector<bool>
no funciona comovector<T>
haría.(Supongo que también es posible que esto sea cierto para cualquier especialización de vector, ya que siempre podemos implementar una nueva. Sin embargo,
std::vector<bool>
es la única especialización estándar en la que la aritmética de puntero simple no funcionará).fuente
std::vector
y todos los demás vectores deben usar almacenamiento contiguo. Por lo tanto,std::vector<bool>
es (afortunadamente) el único vector estándar que es extraño. (Soy muy de la opinión de que esta especialización debería ser obsoleta y reemplazada por, por ejemplo, unastd::dynamic_bitset
con la misma funcionalidad. No es una mala estructura de datos, simplemente no es un vector).Encontré este hilo porque tengo un caso de uso en el que los vectores que usan memoria contigua son una ventaja.
Estoy aprendiendo a usar objetos de búfer de vértice en OpenGL. Creé una clase contenedora para contener la lógica del búfer, por lo que todo lo que necesito hacer es pasar una matriz de flotantes y algunos valores de configuración para crear el búfer. Quiero poder generar un búfer a partir de una función basada en la entrada del usuario, por lo que no se conoce la longitud en el momento de la compilación. Hacer algo como esto sería la solución más sencilla:
Ahora puedo pasar los flotantes del vector como una matriz a las funciones relacionadas con el búfer de OpenGL. Esto también elimina la necesidad de sizeof para determinar la longitud de la matriz.
Esto es mucho mejor que asignar una matriz enorme para almacenar los flotadores y esperar que sea lo suficientemente grande, o hacer mi propia matriz dinámica con almacenamiento contiguo.
fuente
v
lugar de av
sí mismo? porque pasarv
solo hará que se haga una copia dentro de la función, que dejará de existir después de que finalice la función. Por lo tanto, está presionando algo en el vector solo para eliminar el vector cuando finaliza la función.cplusplus.com:
fuente
Sí, se garantiza que los elementos de un std :: vector son contiguos.
fuente