2017-06-01 6 views
6

Donc, je comprends que s2 se lie à l'expression s1 + s1, mais est-ce évalué au moment s2 est affecté ou est-il paresseux et évalué lorsque s2 += "Test"; est appelé? Et aussi s2 conserver la mémoire pour une chaîne temporaire?Quand une valeur est-elle évaluée?

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string s1 = "Test"; 
    std::string&& s2 = s1 + s1; 
    s2 += "Test"; 
    std::cout << s2 << '\n'; 
} 

Répondre

16

s2 se lie à l'expression s1 + s1, mais est-ce évalué au moment s2 est attribué

Oui.

Et aussi s2 maintiendrait de la mémoire pour une chaîne temporaire?

Précisément, s2 est lié à un std::string temporaire.

s1 + s1 produira un std::string temporaire, qui sera lié à la référence s2 (et sa durée de vie est étendue à la durée de vie de la référence). Ensuite s2 += "Test";, exécute operator+=() sur s2, c'est-à-dire le std::string temporaire.

+0

Merci pour la réponse rapide. Il semble que si 's2' était juste un autre' std :: string', les résultats seraient les mêmes, mais les binaires résultants seraient-ils différents? –

+0

@BradyDean Oui, le résultat est le même. C'est difficile à dire sur les binaires de résultats; Quoi qu'il en soit, je l'ai essayé [ici] (https://gcc.godbolt.org/) et il a donné le même assemblage. – songyuanyao

+0

Notez que cela change dans C++ 17 d'une manière qui fait zéro différence observable dans ce cas. – Yakk

2

Les expressions sont toujours évaluées au point où le programme les atteint. Le résultat d'une expression est toujours une valeur (ou un vide).

Les valeurs ont un type et les expressions ont une catégorie de valeur, qui se combinent pour choisir quelle surcharge d'un ensemble de surcharge est utilisée, à un usage particulier.

Dans votre cas, string operator+(...) donne une valeur de chaîne, avec la catégorie pr-value (qui est un type de valeur). Il est alors immédiatement lié à une chaîne & &, donc sa durée de vie est étendue à celle de la référence.

Si vous l'avez affecté à la place à une chaîne simple, string& string::operator=(string&&) aurait été choisi par rapport aux autres surcharges de cet opérateur. Notez que depuis C++ 11, le compilateur est autorisé (et à partir de C++ 17 requis) pour matérialiser la valeur directement dans l'objet cible. Ce processus est connu sous le nom d'élision copier/déplacer ou (N) RVO, pour l'optimisation de la valeur de retour (nommée).

+0

@Yakk Quelles choses en particulier? A ma connaissance, le seul changement est que la construction du mouvement est élidée, et cela n'est pas différent de C++ 14 pour la chaîne – Caleth

+1

Désolé, j'ai juré avoir vu le mot "objet" là où il n'était pas censé être, mais Je ne le vois pas maintenant, donc j'ai dû me tromper. – Yakk