example - vector vector c++
¿Cómo inicializar std:: vector desde C-style array? (5)
¿Cuál es la forma más económica de inicializar un std::vector
desde una matriz C-style?
Ejemplo: en la siguiente clase, tengo un vector
, pero debido a restricciones externas, los datos se pasarán como una matriz estilo C:
class Foo {
std::vector<double> w_;
public:
void set_data(double* w, int len){
// how to cheaply initialize the std::vector?
}
Obviamente, puedo llamar a w_.resize()
y luego recorrer los elementos, o llamar a std::copy()
. ¿Hay algún método mejor?
Bueno, Pavel estaba cerca, pero incluso hay una solución más simple y elegante para inicializar un contenedor secuencial de una matriz de estilo de CA.
En tu caso:
w_ (array, std::end(array))
- array nos conseguirá un puntero al comienzo de la matriz (no captamos su nombre),
- std :: end (array) nos proporcionará un iterador al final de la matriz.
No olvide que puede tratar los punteros como iteradores:
w_.assign(w, w + len);
Puedes ''aprender'' el tamaño de la matriz automáticamente:
template<typename T, size_t N>
void set_data(const T (&w)[N]){
w_.assign(w, w+N);
}
Con suerte, puede cambiar la interfaz a set_data como se indicó anteriormente. Todavía acepta una matriz estilo C como primer argumento. Simplemente sucede tomarlo por referencia.
Cómo funciona
[Actualización: mira here para una discusión más completa sobre cómo aprender el tamaño]
Aquí hay una solución más general:
template<typename T, size_t N>
void copy_from_array(vector<T> &target_vector, const T (&source_array)[N]) {
target_vector.assign(source_array, source_array+N);
}
Esto funciona porque la matriz se está pasando como una referencia a una matriz. En C / C ++, no puede pasar una matriz como una función, sino que se degradará a un puntero y perderá el tamaño. Pero en C ++, puede pasar una referencia a la matriz.
Pasar una matriz por referencia requiere que los tipos coincidan exactamente. El tamaño de una matriz es parte de su tipo. Esto significa que podemos usar el parámetro de la plantilla N para conocer el tamaño para nosotros.
Puede ser incluso más simple tener esta función que devuelve un vector. Con las optimizaciones de compilador adecuadas en efecto, esto debería ser más rápido de lo que parece.
template<typename T, size_t N>
vector<T> convert_array_to_vector(const T (&source_array)[N]) {
return vector<T>(source_array, source_array+N);
}
Usas la palabra inicializar por lo que no está claro si se trata de una tarea única o puede suceder varias veces.
Si solo necesita una inicialización única, puede ponerlo en el constructor y usar el constructor de vectores de dos iteradores:
Foo::Foo(double* w, int len) : w_(w, w + len) { }
De lo contrario, use asignar como se sugirió anteriormente:
void set_data(double* w, int len)
{
w_.assign(w, w + len);
}
std::vector<double>::assign
es el camino a seguir, porque es un código pequeño . Pero, ¿cómo funciona, en realidad? ¿No cambia el tamaño y luego copia? En la implementación de MS de STL que estoy usando lo hace exactamente.
Me temo que no hay una forma más rápida de implementar (re) inicializar su std::vector
.