¿Cómo obtener std :: puntero vectorial a los datos en bruto?

160

Estoy tratando de usar std::vectorcomo una charmatriz.

Mi función toma un puntero vacío:

void process_data(const void *data);

Antes simplemente usaba este código:

char something[] = "my data here";
process_data(something);

Que funcionó como se esperaba.

Pero ahora necesito la dinámica de std::vector, así que probé este código en su lugar:

vector<char> something;
*cut*
process_data(something);

La pregunta es, ¿cómo paso el vector char a mi función para poder acceder a los datos brutos del vector (sin importar el formato que sea: flotantes, etc.)?

Intenté esto:

process_data(&something);

Y esto:

process_data(&something.begin());

Pero devuelve un puntero a los datos e incomprensibles, y éste dio aviso: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Novato
fuente

Respuestas:

238

&somethingle proporciona la dirección del std::vectorobjeto, no la dirección de los datos que contiene. &something.begin()le da la dirección del iterador devuelto por begin()(como advierte el compilador, esto no está técnicamente permitido porque something.begin()es una expresión de valor, por lo que no se puede tomar su dirección).

Suponiendo que el contenedor tiene al menos un elemento, debe obtener la dirección del elemento inicial del contenedor, que puede obtener a través de

  • &something[0]o &something.front()(la dirección del elemento en el índice 0), o

  • &*something.begin()(la dirección del elemento señalado por el iterador devuelto por begin()).

En C ++ 11, se añadió una nueva función miembro a std::vector: data(). Esta función miembro devuelve la dirección del elemento inicial en el contenedor, al igual que &something.front(). La ventaja de esta función miembro es que está bien llamarlo incluso si el contenedor está vacío.

James McNellis
fuente
103
Importante Tenga en cuenta vector<bool>cuál es la excepción a esta respuesta (y no tiene un almacenamiento de memoria contiguo de bools).
Motti
18
En el lado positivo, no hay mucho de qué tener cuidado: estos tres métodos no se compilarán std::vector<bool>porque std::vector<bool>requiere el uso de un objeto proxy y ese proxy no se puede convertir implícitamente en a bool*. Como solución alternativa para esto, si necesita una secuencia de bool, es mejor usar a std::vector<char>. @Motti
James McNellis
Es cierto que el cuidado fue en general y no se dirigió como su respuesta, ya que no hay almacenamiento de memoria contiguo, no hay forma de llegar a él.
Motti
77
por ser comprensivo pero principalmente por .data()- Solo voy a fingir que no lo vi feo &*iterator: P
underscore_d
2
¿Cuánto tiempo volverá el puntero de la data()vida? Si el vector nunca cambia de tamaño, ya sea más grande o más pequeño (a través de push_back()u otras funciones, incluidas reserve), ¿se garantiza que el puntero vivirá tanto tiempo como el vector, señalando el lugar correcto?
johnbakers
81

something.data() devolverá un puntero al espacio de datos del vector.

Chris Dodd
fuente
error C2039: 'data' : is not a member of 'std::vector<_Ty>'
Novato
2
@Rookie: parece que estás usando un compilador roto: 23.3.6.3 en la especificación de C ++ define vector :: data. Intente presentar un error con su proveedor u obtenga un mejor compilador.
Chris Dodd
1
@ Chris Dodd Tengo el mismo error. Estoy usando Visual Studio 2008.
bodacydo
34
@ChrisDodd: vector::data()es nuevo en C ++ 11
HighCommander4
Uso Visual Studio 2012 y deben haber agregado el vector :: data () porque lo uso mucho.
Robert Snyder
12

Tome un puntero al primer elemento en su lugar:

process_data (&something [0]);
Steven Don
fuente
¿Pensé que devolvería la dirección de memoria del primer elemento incluso sin los corchetes de subíndice?
Tim
Eso es para matrices, no para vectores.
Steven Don
Sí, me acabo de dar cuenta, lo siento.
Tim