¿Cuál es la forma más barata de inicializar una std::vector
matriz de estilo C?
Ejemplo: en la siguiente clase, tengo un vector
, pero debido a restricciones externas, los datos se pasarán como una matriz de 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 w_.resize()
y luego recorrer los elementos, o llamar std::copy()
. ¿Hay mejores métodos?
Respuestas:
No olvides que puedes tratar los punteros como iteradores:
fuente
assign
es ciertamente libre de usarlos para optimizar; al menos en VC ++, de hecho hace exactamente eso.v.end()
que un iterador que señala uno más allá del final con el vector en un caso similar). Si obtienes una afirmación, entonces algo está mal en otra parte.Utiliza 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 ponerla en el constructor y usar el constructor de dos iteradores de vectores:
De lo contrario, utilice asignar como se sugirió anteriormente:
fuente
Puede 'aprender' el tamaño de la matriz automáticamente:
Con suerte, puede cambiar la interfaz a set_data como se indicó anteriormente. Todavía acepta una matriz de estilo C como primer argumento. Simplemente lo toma por referencia.
Cómo funciona
[Actualización: vea aquí para una discusión más completa sobre el aprendizaje del tamaño]
Aquí hay una solución más general:
Esto funciona porque la matriz se pasa como una referencia a una matriz. En C / C ++, no puede pasar una matriz como una función, sino que se descompondrá en un puntero y perderá el tamaño. Pero en C ++, tú puedes 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 plantilla N para conocer el tamaño para nosotros.
Puede ser aún más simple tener esta función que devuelve un vector. Con las optimizaciones apropiadas del compilador en efecto, esto debería ser más rápido de lo que parece.
fuente
return { begin(source_array), end(source_array) };
también es posibleBueno, Pavel estuvo cerca, pero incluso hay una solución más simple y elegante para inicializar un contenedor secuencial desde una matriz de estilo ac.
En tu caso:
fuente
array
matriz real (lo que generalmente significa que está copiando desde una matriz global o local (declarada en la función actual)). En el caso del OP, está recibiendo un puntero y una longitud, y debido a que no está tentado en la longitud, no pueden cambiar a recibir un puntero a una matriz de tamaño ni nada, porstd::end
lo que no funcionará.vector
no se sobrecargaoperator()
, por lo que esto no se compilará.std::end
ser llamado en un puntero tampoco sirve (la pregunta pide asignar un vector desde un puntero y una variable de longitud separada).La respuesta genérica rápida:
o pregunta específica:
basado en lo anterior : no olvide que puede tratar los punteros como iteradores
fuente
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 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
.fuente