Dado que std::list
y std::vector
existen, ¿hay alguna razón para usar matrices C tradicionales en C ++, o deberían evitarse, al igual que malloc
?
Dado que std::list
y std::vector
existen, ¿hay alguna razón para usar matrices C tradicionales en C ++, o deberían evitarse, al igual que malloc
?
Respuestas:
En C ++ 11, donde std::array
está disponible, la respuesta es "sí, se deben evitar las matrices". Antes de C ++ 11, es posible que deba utilizar matrices C para asignar matrices en el almacenamiento automático (es decir, en la pila).
Definitivamente, aunque std::array
en C ++ 11, prácticamente solo para datos estáticos. Las matrices de estilo C tienen tres ventajas importantes sobre
std::vector
:
No requieren asignación dinámica. Por esta razón, se prefieren las matrices de estilo C donde es probable que tenga muchas matrices muy pequeñas. Di algo como un punto de n dimensiones:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
Por lo general, uno podría imaginar que dims
será muy pequeño (2 o 3),
T
un tipo integrado ( double
) y que podría terminar
std::vector<Point>
con millones de elementos. Definitivamente no desea millones de asignaciones dinámicas de 3 dobles.
La inicialización estática de soporte. Este es solo un problema para los datos estáticos, donde algo como:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
Esto es a menudo preferible a usar un vector (y std::string
), ya que evita todos los problemas de orden de inicialización; los datos se cargan previamente, antes de que se pueda ejecutar cualquier código real.
Finalmente, relacionado con lo anterior, el compilador puede calcular el tamaño real de la matriz a partir de los inicializadores. No tienes que contarlos.
Si tiene acceso a C ++ 11, std::array
resuelve los dos primeros problemas y definitivamente debe usarse con preferencia a las matrices de estilo C en el primer caso. Sin embargo, no aborda el tercero, y tener la dimensión del compilador de la matriz de acuerdo con el número de inicializadores sigue siendo una razón válida para preferir las matrices de estilo C.
int i[] = { 1, 2, 3 };
sigue trabajando con int i[] = { 1, 2, 3, 4 };
. array<int, 3>
debe cambiarse manualmente a array<int, 4>
.
make_array
función , similar a make_pair
etc. Hat-tip to @R. Martinho Fernandes .
std::array
en C ++ 11, [deberían usarse] prácticamente solo para datos estáticos".
Nunca diga "nunca", pero estoy de acuerdo en que su función se ve muy disminuida por las estructuras de datos reales de STL.
También diría que la encapsulación dentro de los objetos debería minimizar el impacto de elecciones como esta. Si la matriz es un miembro de datos privados, puede intercambiarla sin afectar a los clientes de su clase.
He trabajado en sistemas críticos para la seguridad en los que no puede utilizar la asignación de memoria dinámica. La memoria tiene que estar siempre en la pila. Por lo tanto, en este caso, usaría matrices ya que el tamaño se fija en el momento de la compilación.
std::array<T>
asigna en las pilas y básicamente no tiene gastos generales en una matriz sin formato.
array
in c++
le ofrece una alternativa rápida de tamaño fijo de tamaño dinámico std::vector
y std::list
. std :: array es una de las adiciones en c++11
. Proporciona el beneficio de los contenedores estándar al mismo tiempo que proporciona la semántica de tipo agregado de las matrices de estilo C.
Entonces c++11
, ciertamente usaría std::array
, donde sea necesario, sobre vector. Pero evitaría la matriz de estilo C en C++03
.
Más generalmente, no , no puedo pensar en una razón para utilizar matrices primas sobre, por ejemplo, vectors
. Si el código es nuevo .
Es posible que deba recurrir al uso de matrices si sus bibliotecas necesitan ser compatibles con el código que espera matrices y punteros sin formato.
vector.data()
en C ++ 11 o &vector.front()
anteriormente.
Sé que mucha gente está señalando std :: array para asignar matrices en la pila y std :: vector para el montón. Pero ninguno parece apoyar la alineación no nativa. Si está haciendo cualquier tipo de código numérico en el que desea usar instrucciones SSE o VPX (por lo tanto, requiere una alineación de 128 o 256 bytes respectivamente), las matrices C aún parecen ser su mejor opción.
Yo diría que las matrices siguen siendo útiles, si está almacenando una pequeña cantidad de datos estáticos, ¿por qué no?
La única ventaja de una matriz (por supuesto, envuelta en algo que administrará automáticamente su desasignación cuando sea necesario) sobre la std::vector
que puedo pensar es que vector
no puede pasar la propiedad de sus datos, a menos que su compilador admita C ++ 11 y mueva constructores.
swap
.
Los arreglos de estilo C son una estructura de datos fundamental, por lo que habrá casos en los que sea mejor usarlos. Sin embargo, para el caso general, utilice las estructuras de datos más avanzadas que redondean las esquinas de los datos subyacentes. C ++ te permite hacer cosas muy interesantes y útiles con la memoria, muchas de las cuales funcionan con matrices simples.
std::array
s? En muchos casos, ambos se compilarán en el mismo ensamblado.
std::array
tiene semántica definida con precisión construida sobre matrices estáticas.
Debe usar contenedores STL internamente, pero no debe pasar punteros a dichos contenedores entre diferentes módulos, o terminará en el infierno de dependencias. Ejemplo:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
es una muy buena solución pero no
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
La razón es que std :: string se puede implementar de muchas formas diferentes, pero una cadena de estilo c es siempre una cadena de estilo c.