7
votes

Y a-t-il une différence entre push_back () et redimension (taille () + 1)

Un vecteur standard peut être élargi pour contenir un membre supplémentaire en faisant:

int os = v.size();
v.resize(os+1);
v[os] = 1;


6 commentaires

Ce sont des fonctions différentes conçues à des fins différentes. Les comparer pour leur "vitesse" ne sont pas utiles.


push_back n'est pas TERSE; redimensionner est verbose!


@meagar - mais élargissent-ils la mémoire de la même manière?


Ce fil peut être utile pour répondre à votre question << A HREF = "http://stackoverflow.com/questions/1902832/Resize-STSUS-PUSH-Back-In-StdVector-Does-it-avoid-an-unnessary-Copy-Copy -Assig "title =" redimensionner par rapport à la poussée dans STDVector permet d'éviter une copie inutile Assig "> Stackoverflow.com/Questtions/1902832/... >


Si votre vis est ajouté, push_back est un tournevis et redimensionnement (taille () + 1) + affectation est un marteau. Vous pourriez obtenir la vis, mais c'est clairement maintenant ce que l'outil a été conçu pour.


@Andrews. Pourquoi ne regardez-vous pas simplement le code de push_back pour voir s'il y a une différence?


5 Réponses :


8
votes

push_back construira en place, ce qui signifie qu'il appelle le constructeur de copie.

redimensionner appellera le constructeur par défaut, puis V [OS] appellera l'opérateur d'affectation.

Utiliser push_back .


La légèreté dit, les allocations dans les deux cas sont équivalentes. Voir sa réponse pour plus de détails.

Voici un exemple: http://stacked-crooked.com/view?id=43766666E5C72D282BD94C05E43E8897 / a>



5
votes

Expansion de la mémoire

Mais élargissent-ils la mémoire de la même manière? P> blockQuote>

Il n'est pas spécifié explicitement en C ++ 11 (j'ai vérifié), mais oui fort>. p>

redimensionner code> dans ce cas est défini pour "ajouter au conteneur", la seule interprétation logique dont le rend l'équivalent à insérer code> et push_back code> en termes d'allocation. P>

Le Le dos de la mise en oeuvre du conteneur attribue généralement «plus de besoins» dans tous les cas où son bloc de mémoire est élargi - cela se fait par la norme ne l'interdisant pas em> plutôt que le mandataire standard, et là-bas n'est pas un libellé de suggérer que ce n'est pas le cas pour redimensionner code> aussi. p>

En fin de compte, alors, il est complètement à la mise en œuvre, mais je serais surpris de voir une différence Dans les règles d'allocation de mémoire entre les deux approches sur tout compilateur traditionnel. P>

Cet essai montre un exemple simple: p> xxx pré>

Notez que Celui-ci est subtilement différent: P>

int main() {
    std::vector<int> a, b;

    for(int i = 0; i != 100; ++i)
      a.push_back(0);
    b.resize(100);

    std::cout << a.capacity() << " , " << b.capacity() << std::endl;
}

// Output from my GCC 4.7.2:
//  128 , 100


Performance concerne h3>

Quoi qu'il en soit, comme @pubby identifie, dans le cas de redimensionner code>, vous ferez la construction implicite suivie de L'affectation explicite, non optimale si vous optimisez prématurément. P>

dans le monde réel, le problème réel ici est en utilisant la mauvaise fonction pour le travail em> et écrire du code idiot em>. p> h3>


0 commentaires

1
votes

Ouais, il peut y avoir une différence significative, en particulier lors de l'utilisation de types de données personnalisés. Observez: xxx

sortie: xxx

push_back FTW EDIT: En réponse aux courses de @lighness dans le commentaire d'orbite, c'est bien sûr un exemple idiot. S n'est évidemment pas un "code" vraiment "utile", struct , et si vous supprimez toutes les instructions d'impression ou définissez simplement s comme structurer s {}; , puis bien sûr, le compilateur peut optimiser beaucoup.

mais depuis quand êtes-vous seulement Utilisez des types de données incroyablement triviaux dans un programme? Vous utiliserez des types de données triviaux, mais vous utiliserez également des types de données non triviaux un jour aussi. Ces types de données non triviaux peuvent avoir des constructeurs, destructeurs ou des gestionnaires d'affectation coûteux (ou ils peuvent ne pas être super coûteux, mais ils peuvent s'ajouter si vous utilisez à plusieurs reprises redimensionner au lieu de push_back ), et push_back serait certainement le bon choix.


3 commentaires

Est-ce vraiment significatif ? Ces appels seront optimisés lorsque vous supprimez les lignes STD :: COUT .


@LightnessRacesInorbit: Le point est que si vous avez du type de données avec des constructeurs non triviaux, des opérateurs d'affectation ou des destructeurs que vous devrez payer pour cela. Bien sûr, les choses triviales ne comptent pas beaucoup (comme l'exemple de int dans la question); Pour les types de données non triviaux, cependant, il peut s'additionner.


Je ne vais pas suggérer que quiconque utilise redimensionner + attribution sur push_back , bien sûr; Je ne vais tout simplement pas accepter que cela ne soit nulle part près du goulot d'étranglement dans plus de 1% des cas :)



3
votes

Ils ne sont pas comparables et vous ne devez pas baser la décision sur la performance, mais cela étant dit que la performance pourrait différer beaucoup en fonction de la mise en œuvre.

La norme nécessite push_back () pour avoir une durée constante amortise, ce qui signifie fondamentalement que la mise en oeuvre doit augmenter la mémoire tampon pour les objets à la suite d'une série géométrique (c'est-à-dire lors de la croissance de la nouvelle taille, la nouvelle taille doit être proportionnelle. à la taille précédente par un facteur F> 1).

Il n'y a pas de telles exigences pour redimension () . En fait, certaines implémentations supposent que si vous appelez redimensionnement () c'est parce que vous avez une meilleure connaissance de la taille finale du vecteur. Dans cet esprit, ces implémentations cultiveront la mémoire tampon (si nécessaire) à exactement la taille que vous demandez, ne suivez pas une progression géométrique. Cela signifie que le coût de l'annexe suivant ce mécanisme peut être O (n ^ 2), au lieu de O (n) pour le boîtier push_back .


0 commentaires

0
votes

redized () code> peut mieux allouer la mémoire lorsque vous devez ajouter quelques éléments supplémentaires.

Ie p>

v.reserve(os.size() + n);


0 commentaires