2
votes

Conteneurs vs pointeurs intelligents en C ++

Comment puis-je choisir entre std :: containers ( std :: vector ou std :: array ) et des pointeurs intelligents pointant vers des tableaux

Je sais les conteneurs sont des objets pour la gestion de la mémoire. Ils sont exceptionnellement sûrs et il n'y aura pas de fuite de mémoire et ils fournissent également la vérification des fonctions de gestion de la mémoire (push.back, etc.) et les pointeurs intelligents sont des pointeurs qui ne fuient pas non plus la mémoire car ils les suppriment quand ils ne sont plus nécessaires ( comme unique_ptr lors de la sortie de champ). Il est probable que les conteneurs comportent une surcharge à chaque fois qu'ils sont créés.

Ma question est de savoir comment puis-je décider de la méthode à utiliser et pourquoi.

std::vector <unsigned char>myArray(3 * outputImageHight * outputImageWidth);

std::unique_ptr<unsigned char[]>myArray(new unsigned char[3 * outputImageHight * outputImageWidth]);


8 commentaires

Toujours par défaut, un conteneur, dans 99,99% de tous les cas, il sera correct.


Sauf si vous mesurez une baisse de performance parce que vous avez quelque chose qui ne serait pas là dans le brut unique_ptr . Ce serait le 0,01%.


Veuillez remplacer l'image par le texte à la place.


@MatthieuBrucher Et cette baisse de performance est l'un des trois principaux goulots d'étranglement du programme.


Ainsi, les pointeurs intelligents pour les tableaux n'existent que pour 0,01% des cas


Petite note, utilisez make_unique au lieu de new + ctor. raisons


La prochaine fois que vous poserez une question, veuillez ne pas publier d'images de code au lieu de code sous forme de texte.


Je poste une photo parce que je n'ai pas pu publier le code correctement. Le message a été édité par un autre utilisateur.


3 Réponses :


3
votes

J'utiliserais le vecteur. Votre version de pointeur n'offre pratiquement aucune amélioration par rapport au vecteur et vous perdez beaucoup de fonctionnalités utiles. Vous devrez probablement mesurer la taille et itérer votre tableau à un moment donné, avec un vecteur que vous obtenez gratuitement, alors que vous devrez l'implémenter vous-même pour votre version de pointeur; à ce stade, vous pouvez aussi bien avoir utilisé le vecteur pour commencer.

Il peut y avoir un coût de performance pour instancier le vecteur, mais je doute que ce soit un goulot d'étranglement pour la plupart des applications. Si vous créez tellement de vecteurs que leur instanciation vous coûte du temps, vous pouvez probablement être plus intelligent dans leur gestion (mise en commun de votre mémoire, allocateurs de vecteurs personnalisés, etc.). En cas de doute, mesurez.

Un exemple où vous pourriez avoir besoin d'utiliser la version unique_ptr pourrait être si vous travaillez avec une bibliothèque écrite en C dont vous perdez la propriété du tableau. Par exemple:

std::unique_ptr<unsigned char[]>myArray(
    new unsigned char[3 * outputImageHight * outputImageWidth]);

my_c_lib_data_t cLibData;
int result = my_c_lib_set_image(cLibData, myArray);

if (MYLIB_SUCCESS == result)
    // mylib successfully took ownership of the char array, so release the pointer.
    myArray.release();

Si vous avez le choix, préférez utiliser des conteneurs de style C ++ là où vous le pouvez.


2 commentaires

En fait, j'ai besoin d'itérer au niveau du tableau et j'ai besoin de mesurer la taille et de l'implémenter moi-même. Et j'ai aussi pensé à cela, mais ma question est que s'il n'y a jamais de raison d'utiliser des pointeurs intelligents pour les tableaux, pourquoi les ajoutent-ils même?


@Aris - Bonne question! J'ai ajouté un paragraphe supplémentaire à ma réponse qui couvre un exemple où la version unique_ptr pourrait être utile.



0
votes

Utilisez toujours des conteneurs STL sauf dans les cas où vous avez de bonnes raisons d'utiliser des pointeurs. Les raisons sont la fiabilité et la lisibilité, IMO.


0 commentaires

3
votes

std :: vector , principalement parce qu'il représente mieux la «séquence d'éléments en mémoire contiguë», c'est la représentation par défaut pour cela, et permet un large éventail d'opérations courantes.

vector a une sémantique de déplacement, donc l'avantage de std :: unique_ptr est limité.

Si vous avez de la chance, votre implémentation STL `fournit une petite optimisation vectorielle, en ignorant l'allocation de mémoire pour les petites tailles.
- edit: Je n'étais pas au courant que SBO est apparemment interdit par la norme - désolé d'avoir suscité vos espoirs, merci @KarlNicholl

Si la sémantique du pointeur est requise, un unique_ptr> ou shared_ptr> est un choix valide avec peu de frais généraux.

boost a introduit shared_array etc., qui représentent mieux votre deuxième option, mais je ne les ai pas vus obtenir beaucoup de traction.


2 commentaires

L'optimisation des petits vecteurs est-elle prise en charge dans std :: vector de nos jours? Enfin, je savais que cela n'était pas autorisé car swap () invaliderait potentiellement les itérateurs avec une implémentation de vecteur SBO, ce qui n'est pas autorisé (voir ici stackoverflow.com/a/8191356/52724 ). Cela dit, boost :: container :: small_vector existe et est utile pour l'optimisation des petits tampons.


@KarlNicoll - Aww, mec, dommage - n'était pas au courant de cela. J'ai édité la réponse.