Depuis std::list
et std::vector
existent, y a-t-il une raison d'utiliser des tableaux C traditionnels en C ++, ou devraient-ils être évités, tout comme malloc
?
Depuis std::list
et std::vector
existent, y a-t-il une raison d'utiliser des tableaux C traditionnels en C ++, ou devraient-ils être évités, tout comme malloc
?
Réponses:
Dans C ++ 11 où std::array
est disponible, la réponse est "oui, les tableaux doivent être évités". Avant C ++ 11, vous devrez peut-être utiliser des tableaux C pour allouer des tableaux dans le stockage automatique (c'est-à-dire sur la pile).
Certainement, bien qu'avec std::array
C ++ 11, pratiquement uniquement pour les données statiques. Les tableaux de style C présentent trois avantages importants par rapport à
std::vector
:
Ils ne nécessitent pas d'allocation dynamique. Pour cette raison, les tableaux de style C doivent être préférés là où vous êtes susceptible d'avoir beaucoup de très petits tableaux. Dites quelque chose comme un point à n dimensions:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
Typiquement, on pourrait imaginer un qui dims
sera très petit (2 ou 3),
T
un type intégré ( double
), et que vous pourriez vous retrouver avec
std::vector<Point>
des millions d'éléments. Vous ne voulez certainement pas des millions d'allocations dynamiques de 3 doubles.
L'initialisation statique de support. Ce n'est un problème que pour les données statiques, où quelque chose comme:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
Ceci est souvent préférable à l'utilisation d'un vecteur (et std::string
), car cela évite tous les problèmes d'ordre d'initialisation; les données sont préchargées avant qu'un code réel puisse être exécuté.
Enfin, lié à ce qui précède, le compilateur peut calculer la taille réelle du tableau à partir des initialiseurs. Vous n'êtes pas obligé de les compter.
Si vous avez accès à C ++ 11, std::array
résout les deux premiers problèmes et devrait certainement être utilisé de préférence aux tableaux de style C dans le premier cas. Cependant, cela n'aborde pas le troisième et le fait que le compilateur dimensionne le tableau en fonction du nombre d'initialiseurs est toujours une raison valable pour préférer les tableaux de style C.
int i[] = { 1, 2, 3 };
continue de travailler avec int i[] = { 1, 2, 3, 4 };
. array<int, 3>
doit être changé manuellement en array<int, 4>
.
make_array
fonction , similaire à make_pair
etc. Pointe du chapeau à @R. Martinho Fernandes .
std::array
en C ++ 11, [ils devraient être utilisés] pratiquement uniquement pour les données statiques».
Ne dites jamais «jamais», mais je conviens que leur rôle est grandement diminué par les véritables structures de données de STL.
Je dirais également que l'encapsulation à l'intérieur des objets devrait minimiser l'impact de choix comme celui-ci. Si le tableau est un membre de données privé, vous pouvez l'échanger vers l'intérieur ou l'extérieur sans affecter les clients de votre classe.
J'ai travaillé sur des systèmes critiques de sécurité où vous ne pouvez pas utiliser l'allocation de mémoire dynamique. La mémoire doit toujours être sur la pile. Par conséquent, dans ce cas, vous utiliserez des tableaux car la taille est fixée au moment de la compilation.
std::array<T>
alloue sur les piles et n'a fondamentalement aucune surcharge sur un tableau brut.
array
in c++
vous donne une alternative rapide de taille fixe de taille dynamique std::vector
et std::list
. std :: array est l'un des ajouts dans c++11
. Il offre l'avantage des conteneurs std tout en fournissant la sémantique de type agrégé des tableaux de style C.
Donc , c++11
j'utiliserais certainement std::array
, là où c'est nécessaire, sur le vecteur. Mais j'éviterais les tableaux de style C dans C++03
.
Le plus souvent, non , je ne peux pas penser à une raison d'utiliser des tableaux bruts, par exemple vectors
. Si le code est nouveau .
Vous devrez peut-être recourir à des tableaux si vos bibliothèques doivent être compatibles avec du code qui attend des tableaux et des pointeurs bruts.
vector.data()
en C ++ 11 ou &vector.front()
antérieur.
Je sais que beaucoup de gens indiquent std :: array pour allouer des tableaux sur la pile, et std :: vector pour le tas. Mais aucun ne semble prendre en charge l'alignement non natif. Si vous faites n'importe quel type de code numérique sur lequel vous souhaitez utiliser les instructions SSE ou VPX (nécessitant ainsi respectivement un alignement de 128 ou 256 octets), les tableaux C semblent toujours être votre meilleur pari.
Je dirais que les tableaux sont toujours utiles, si vous stockez une petite quantité statique de données, pourquoi pas.
Le seul avantage d'un tableau (bien sûr enveloppé dans quelque chose qui gérera automatiquement sa désallocation en cas de besoin) sur lequel std::vector
je peux penser est qu'il vector
ne peut pas transmettre la propriété de ses données, à moins que votre compilateur ne prenne en charge C ++ 11 et déplace les constructeurs.
swap
.
Les tableaux de style C sont une structure de données fondamentale, il y aura donc des cas où il est préférable de les utiliser. Pour le cas général, cependant, utilisez les structures de données plus avancées qui arrondissent les coins des données sous-jacentes. C ++ vous permet de faire des choses très intéressantes et utiles avec la mémoire, dont beaucoup fonctionnent avec des tableaux simples.
std::array
s? Les deux seront dans de nombreux cas compilés dans le même assembly.
std::array
a une sémantique définie avec précision construite sur des tableaux statiques.
Vous devez utiliser des conteneurs STL en interne, mais vous ne devez pas passer de pointeurs vers de tels conteneurs entre différents modules, sinon vous vous retrouverez dans l'enfer des dépendances. Exemple:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
est une très bonne solution mais pas
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
La raison en est que std :: string peut être implémenté de différentes manières, mais une chaîne de style C est toujours une chaîne de style C.