Estoy empezando a entrar en C ++ y quiero aprender algunos buenos hábitos. Si acabo de asignar una matriz de tipos int
con el new
operador, ¿cómo puedo inicializarlos a 0 sin recorrerlos todos yo mismo? ¿Debo usar memset
? ¿Hay una manera "C ++" de hacerlo?
c++
initialization
memory-management
new-operator
dreamlax
fuente
fuente
&vector[0]
.Respuestas:
Es una característica sorprendentemente poco conocida de C ++ (como lo demuestra el hecho de que nadie ha dado esto como respuesta todavía), pero en realidad tiene una sintaxis especial para inicializar un conjunto de valores:
Tenga en cuenta que debe usar los paréntesis vacíos; no puede, por ejemplo, usar
(0)
ni nada más (por lo que esto solo es útil para la inicialización de valores).Esto está explícitamente permitido por ISO C ++ 03 5.3.4 [expr.new] / 15, que dice:
y no restringe los tipos para los que está permitido, mientras que el
(expression-list)
formulario está restringido explícitamente por otras reglas en la misma sección, de modo que no permite tipos de matriz.fuente
new int[10] {}
. También puede proporcionar valores para inicializar con:new int[10] {1,2,3}
Suponiendo que realmente desea una matriz y no un std :: vector, la "forma C ++" sería esta
Pero tenga en cuenta que, en realidad, esto sigue siendo en realidad solo un bucle que asigna cada elemento a 0 (realmente no hay otra forma de hacerlo, salvo una arquitectura especial con soporte a nivel de hardware).
fuente
Hay varios métodos para asignar una matriz de tipo intrínseco y todos estos métodos son correctos, aunque cuál elegir, depende ...
Inicialización manual de todos los elementos en bucle.
Usando la
std::memset
función de<cstring>
Usando
std::fill_n
algoritmo de<algorithm>
Utilizando
std::vector
contenedorSi C ++ 0x está disponible, usando las características de la lista de inicializador
fuente
int array[SIZE] ={1,2,3,4,5,6,7};
notación, puedo usarvoid rotateArray(int (& input)[SIZE], unsigned int k);
sería mi declaración de función, ¿qué sería al usar la primera convención? ¿cualquier sugerencia?std::memset
es incorrecto: pasa 10, parece esperar un número de bytes; consulte en.cppreference.com/w/cpp/string/byte/memset . (Creo que esto muestra muy bien por qué debería uno evitar tal construcción de bajo nivel cuando sea posible.)Si la memoria que está asignando es una clase con un constructor que hace algo útil, el operador new llamará a ese constructor y dejará su objeto inicializado.
Pero si está asignando un POD o algo que no tiene un constructor que inicialice el estado del objeto, entonces no puede asignar memoria e inicializar esa memoria con el operador nuevo en una operación. Sin embargo, tiene varias opciones:
1) Use una variable de pila en su lugar. Puede asignar e inicializar por defecto en un paso, de esta manera:
2) uso
memset()
. Tenga en cuenta que si el objeto que está asignando no es un POD , es una mala idea memorizarlo. Un ejemplo específico es que si configura una clase que tiene funciones virtuales, eliminará la vtable y dejará su objeto en un estado inutilizable.3) Muchos sistemas operativos tienen llamadas que hacen lo que usted desea: asignar en un montón e inicializar los datos a algo. Un ejemplo de Windows sería
VirtualAlloc()
4) Esta suele ser la mejor opción. Evite tener que manejar la memoria usted mismo. Puede usar contenedores STL para hacer casi cualquier cosa que haría con la memoria sin procesar, incluida la asignación e inicialización de una sola vez:
fuente
Sí hay:
Use un vector en lugar de una matriz asignada dinámicamente. Los beneficios incluyen no tener que molestarse en eliminar explícitamente la matriz (se elimina cuando el vector se sale del alcance) y también que la memoria se elimina automáticamente incluso si se produce una excepción.
Editar: para evitar más votos negativos por parte de personas que no se molestan en leer los comentarios a continuación, debo dejar más claro que esta respuesta no dice que el vector sea siempre la respuesta correcta. Pero seguro que es una forma más C ++ que "manualmente" asegurándose de eliminar una matriz.
Ahora con C ++ 11, también hay std :: array que modela una matriz de tamaño constante (frente a un vector que puede crecer). También hay std :: unique_ptr que gestiona una matriz asignada dinámicamente (que se puede combinar con la inicialización como se responde en otras respuestas a esta pregunta). Cualquiera de esos es una forma más C ++ que manejar manualmente el puntero a la matriz, en mi humilde opinión.
fuente
std::vector
lugar de arreglos asignados dinámicamente? ¿Cuáles son los beneficios de usar una matriz sobre un vector y viceversa?std::vector
.vector
todas partes, independientemente del contexto, se llama "Escribir código Java en C ++".std::fill
es unidireccional Toma dos iteradores y un valor para llenar la región. Eso, o el bucle for, sería (supongo) la forma más C ++.Para establecer una matriz de tipos enteros primitivos en 0 específicamente,
memset
está bien, aunque puede levantar las cejas. Considere tambiéncalloc
, aunque es un poco incómodo usarlo desde C ++ debido al reparto.Por mi parte, casi siempre uso un bucle.
(No me gusta adivinar las intenciones de las personas, pero es cierto que
std::vector
, en igualdad de condiciones, es preferible usarlasnew[]
).fuente
siempre puedes usar memset:
fuente
memset
, pero no estaba seguro de si esta era la forma en C ++ de abordar el problema.10 * sizeof( *myArray )
está más documentado y a prueba de cambios que10 * sizeof( int )
.Por lo general, para listas dinámicas de elementos, utiliza a
std::vector
.En general, uso memset o un bucle para la asignación dinámica de memoria sin procesar, dependiendo de qué tan variable prevea que será esa área de código en el futuro.
fuente