2017-01-19 4 views
1

C'est une question très basique, mais je n'arrive pas à comprendre la logique de ce qui se passe ici. Considérons l'extrait de code:Quel vecteur C++ push_back est appelé pour les objets créés à l'intérieur d'une boucle

class Board{ 
private: 
    vector< vector<Cell> > allCells; 
    int bheight; 
    int bwidth; 
public: 
    Board(int width = 10, int height = 10){ 
     bheight = height; bwidth = width; 
     allCells.resize(width); 
     #loop for creating cell objects 
     for(int i = 0; i < width; i++){ 
      allCells[i].reserve(height); 
      for(int j = 0; j < height; j++){ 
       Cell aCell(i,j,0); #an object created inside a loop 
       allCells[i].push_back(aCell); #push it into a vector 
      } 

     } 
    } 

Ce code fonctionne bien dire après la sortie du constructeur, tous les objets dans le vecteur (des vecteurs) allCells stocke toujours des informations appropriées. Ma question est la suivante: comment cela a-t-il été réalisé? Par définition, vector.push_back n'a que deux variantes:

void push_back (const value_type& val); 
void push_back (value_type&& val); 

Il ne peut appeler la deuxième variante puisque l'objet aCell temporaire est un objet lvalue. S'il appelle la première variante, il pousse l'objet temporaireaCell, qui est détruit lorsque la boucle se termine.

Toute explication de ce qui se passe sous le capot de ceci est appréciée.

EDIT: code fixe en raison d'une erreur signalée par Sam Varshavchik et songyuanyao

+0

[Le nouvel élément est initialisé en tant que copie de 'value'.] (Http://en.cppreference.com/w/cpp/container/vector/push_back). – user657267

+0

Ahh donc l'objet push_back dans la première variante n'est pas l'objet créé, mais plutôt un objet créé par le constructeur copy de l'argument? – TuanDT

+0

Oups nvm, j'ai mal lu. Pardon. –

Répondre

2

Si elle appelle la première variante, il pousse l'objet temporaire aCell, qui est détruit lorsque la boucle se termine.

Oui, la première version est appelée car aCell est une lvalue. C'est bien parce que l'élément push_back ed est initialisé par copie à partir de l'argument; il est indépendant de la variable locale aCell.

Ajoute la valeur de l'élément donné à la fin du conteneur.

1) Le nouvel élément est initialisé comme une copie de valeur.

BTW: Votre code a un comportement non défini quand allCells[i] est utilisé dans la boucle, car allCells est encore vide à ce moment-là, il n'a pas d'éléments. Note reserve ne changera pas la taille mais la capacité du vector, mais resize fait.

Board(int width = 10, int height = 10){ 
    bheight = height; bwidth = width; 
    allCells.reserve(width);   // it should be allCells.resize(width) !! 
    #loop for creating cell objects 
    for(int i = 0; i < width; i++){ 
     allCells[i].reserve(height); 
     for(int j = 0; j < height; j++){ 
      Cell aCell(i,j,0); #an object created inside a loop 
      allCells[i].push_back(aCell); #push it into a vector 
     } 
    } 
} 
+0

ahh merci pour le pointeur sur le bug dans le code. Je viens de le réparer. – TuanDT