Un poco plantea la pregunta de por qué? Puede acceder a un vector como una matriz. ¿Qué hace una matriz que no hace un vector?
Michael Dorgan
96
@Michael El caso de uso típico que tengo es el uso de un vector en mi propio código y la necesidad de llamar a una función de terceros que toma una matriz
Michael Mrozek
77
La terminología que se arroja es confusa. Un puntero no es una matriz. ¿Queremos un puntero al primer elemento de una matriz, o una matriz?
GManNickG
77
absolutamente una pregunta real, bastante simple, fácil de interpretar también. por favor vuelva a abrir.
dbliss
10
"Un poco plantea la pregunta de por qué?" - Primero, mal uso de esa frase. En segundo lugar, es muy evidente por qué.
Jim Balter
Respuestas:
533
Hay un truco bastante simple para hacerlo, ya que la especificación ahora garantiza que los vectores almacenen sus elementos de forma contigua:
@ganuke No estás copiando, estás haciendo un puntero que apunta a la matriz real que el vector está usando internamente. Si desea copiar la respuesta de GMan explica cómo
Michael Mrozek
44
@ganuke: ¿Qué es "la matriz"? Necesitas dar más información. ¿Cuál es el panorama general?
GManNickG
66
@ganuke No, solo necesitas un double*que apunte a los mismos datos. Esta respuesta funciona exactamente para ese caso
Michael Mrozek
66
@guneykayim El vector posee ese recuerdo, no deberías liberarlo
Michael Mrozek
23
std::vector<double> v; double* a = v.data();
sinoTrinity
148
¿Para qué? Necesita aclarar: ¿Necesita un puntero al primer elemento de una matriz o una matriz?
Si está llamando a una función API que espera lo primero, puede hacerlo do_something(&v[0], v.size()), donde ves un vector de doubles. Los elementos de un vector son contiguos.
De lo contrario, solo tiene que copiar cada elemento:
Nota: use v.size () para obtener el número de elementos para la nueva matriz: double arr [v.size ()];
rbaleksandar
77
@rbaleksandar: Las matrices no pueden tener un tamaño de expresión no constante.
GManNickG
@GManNickG: Funciona pero creo que hay algunos malentendidos aquí. Imagine lo siguiente: tiene una clase con un montón de punteros de varios tipos que tienen que apuntar a matrices, que no se conocen en el momento en que define su clase y que luego se crean al vaciar varios vectores y usar su parámetro de tamaño para determinar cuánto espacio se va a usar. Otro ejemplo: una función simple void arrayTest (unsigned int arrSize), que crea una matriz (short arr [arrSize];) usando su parámetro de función para el tamaño.
rbaleksandar
1
@rbaleksandar Sin malentendidos; en C ++ 11 y anteriores, los tamaños de matriz deben ser expresiones constantes integrales. Su ejemplo de función es un uso común para VLA en C, pero solo es compatible con la extensión (no estándar) en C ++. Sin embargo, puede llegar a C ++ 14: stackoverflow.com/a/17318040/87234 . Pero a partir de ahora, simplemente no es una opción estándar.
GManNickG
1
@GManNickG Creo que @Jet está diciendo que si desea convertir un vector en una matriz, y tiene la intención de cambiar el tamaño de la matriz usando la size()función de la std:vectorque necesitará usar newo mallocpara hacer eso. Como ya se señaló (por usted) eso double arr[v.size()]no es válido. Usar un vector en lugar de nuevo es una buena idea, pero el punto principal de la pregunta es cómo puede convertir un vector en una matriz.
Se garantiza que esto funcione de manera estándar, sin embargo, existen algunas advertencias: en particular, tenga cuidado de usar solo thearraymientras thevectoresté dentro del alcance.
Si usted tiene una función, entonces es probable que tenga la siguiente: foo(&array[0], array.size());. Si logró entrar en una situación en la que necesita una matriz, entonces necesita refactorizar, los vectores son básicamente matrices extendidas, siempre debe usarlas.
Respuestas:
Hay un truco bastante simple para hacerlo, ya que la especificación ahora garantiza que los vectores almacenen sus elementos de forma contigua:
fuente
double*
que apunte a los mismos datos. Esta respuesta funciona exactamente para ese casostd::vector<double> v; double* a = v.data();
¿Para qué? Necesita aclarar: ¿Necesita un puntero al primer elemento de una matriz o una matriz?
Si está llamando a una función API que espera lo primero, puede hacerlo
do_something(&v[0], v.size())
, dondev
es un vector dedouble
s. Los elementos de un vector son contiguos.De lo contrario, solo tiene que copiar cada elemento:
Asegúrese de que no solo
arr
sea lo suficientemente grande, sino quearr
se llene, o de que tenga valores no inicializados.fuente
size()
función de lastd:vector
que necesitará usarnew
omalloc
para hacer eso. Como ya se señaló (por usted) esodouble arr[v.size()]
no es válido. Usar un vector en lugar de nuevo es una buena idea, pero el punto principal de la pregunta es cómo puede convertir un vector en una matriz.Para C ++ 11 ,
vector.data()
hará el truco.fuente
Se garantiza que esto funcione de manera estándar, sin embargo, existen algunas advertencias: en particular, tenga cuidado de usar solo
thearray
mientrasthevector
esté dentro del alcance.fuente
empty()
, de lo contrario, esto invocaría al temido UB.Los vectores efectivamente son matrices debajo de la piel. Si tienes una función:
puedes llamarlo así:
Nunca debería necesitar convertir un vector en una instancia de matriz real.
fuente
f( &v[0] );
a tu última líneaEn cuanto a
std::vector<int> vec
vec para obtenerint*
, puede usar dos métodos:int * arr = & vec [0];
int * arr = vec.data ();
Si desea convertir cualquier tipo de
T
vector aT* array
, simplemente reemplace el anteriorint
aT
.Te mostraré por qué los dos anteriores funcionan, para una buena comprensión.
std::vector
Es una matriz dinámica esencialmente.Miembro de datos principal de la siguiente manera:
El
range (start_, end_of_storage_)
es toda la memoria de matriz que asigna el vector;El
range(start_, finish_)
es toda la memoria de matriz que utiliza el vector;El
range(finish_, end_of_storage_)
es la memoria de la matriz de respaldo.Por ejemplo, en cuanto a un vector vec. que tiene {9, 9, 1, 2, 3, 4} es un puntero como el siguiente.
So
&vec[0]
= start_ (address.) (Start_ es equivalente a int * array head)En
c++11
ladata()
función miembro simplemente devuelve start_fuente
Podemos hacer esto usando el método data (). C ++ 11 proporciona este método.
Fragmento de código
fuente
fuente
Si usted tiene una función, entonces es probable que tenga la siguiente:
foo(&array[0], array.size());
. Si logró entrar en una situación en la que necesita una matriz, entonces necesita refactorizar, los vectores son básicamente matrices extendidas, siempre debe usarlas.fuente
Puedes hacer algo como esto
fuente