2017-02-28 1 views
3
#include <vector> 

using namespace std; 

void f(const vector<int>&) {} 
void f(vector<int>&&) {} 

int main() 
{ 
    { 
     vector<int> coll; 

     // 
     // coll is dying, so, 
     // "f(coll)" will call "f(const vector<int>&)" or 
     // "f(vector<int>&&)" as per C++11? 
     // 
     f(coll); 
    } 
} 

Dans le code ci-dessus, coll est en train de mourir; Ainsi, f(coll) appellera f(const vector<int>&) ou f(vector<int>&&) selon C++ 11?Est-ce que C++ 11 garantit qu'un objet mourant sera déplacé plutôt que copié en tant qu'argument?

+9

Non; dans ce cas, il appellera 'f (const std :: vector &)'. Dans l'appel que vous faites, 'coll' est une lvalue nommée. Le fait que 'coll' sera hors de portée dans la ligne suivante n'est pas pertinent. Si vous voulez appeler la version rvalue de 'foo', alors vous devriez utiliser' f (std :: move (coll)) '. –

+0

Que voulez-vous dire _ "' 'coll' est en train de mourir" _? Il sera détruit après l'appel. Vous avez probablement signifié quelque chose comme 'foo (vecteur ());' –

+1

'coll' n'est pas" en train de mourir "(sortir de la portée) avant l'accolade'} '. Dans l'accolade, c'est parfaitement sain :-) Par conséquent, si vous voulez obtenir un rvalue vous avez besoin d'un explicite 'std :: move (coll)' – AndyG

Répondre

5

Si f(coll) appelé f(vector<int>&&) au lieu de f(const vector<int>&) ce serait une violation de la norme, car il faudrait choisir la mauvaise fonction de surcharge.

Il serait également plutôt déroutant si la résolution de l'appel était différente en fonction de l'emplacement de l'appel et s'il y a des instructions ultérieures après l'appel en utilisant coll.

Le traitement spécial est donné à return values seulement:

Si expression est une expression lvalue et les conditions de copie élision sont atteints ou seraient atteints, sauf que les noms d'expression d'un paramètre de fonction, La résolution de surcharge pour sélectionner le constructeur à utiliser pour l'initialisation de la valeur retournée est effectuée deux fois: d'abord comme si expression était une expression rvalue (donc elle peut sélectionner le constructeur de déplacement ou un constructeur de copie en référence à const) disponible, la résolution de surcharge est effectuée la deuxième fois, avec l'expression lvalue (donc il peut sélectionner le flic y constructeur prenant une référence à non-const).

+5

Juste pour ajouter à ceci: il y a une très forte raison pour * non * permettre le compilateur pour appeler la version rvalue de 'foo' dans ce cas (même si' coll' est définitivement hors de portée dans la ligne suivante). C'est parce que si cela était permis, alors si quelqu'un devait ajouter une déclaration qui utilisait 'coll' dans la ligne suivante, le comportement du programme changerait; ce qui serait déroutant pour la plupart des gens. –