web-dev-qa-db-fra.com

Passer par référence à un constructeur

J'ai décidé de voir si l'attribution d'une référence à un membre ferait d'un membre une référence. J'ai écrit l'extrait suivant pour le tester. Il existe une classe simple Wrapper avec un std::string Comme variable membre. Je prends un const string& Dans le constructeur et je l'assigne à la variable membre publique. Plus tard dans la méthode main() je modifie la variable membre mais le string que j'ai transmis au constructeur reste inchangé, comment se fait-il? Je pense qu'en Java la variable aurait changé, pourquoi pas dans cet extrait de code? Comment fonctionnent exactement les références dans ce cas?

#include <iostream>
#include <string>
using namespace std;

class Wrapper
{
public:
   string str;

   Wrapper(const string& newStr)
   {
      str = newStr;
   }
};

int main (int argc, char * const argv[]) 
{
   string str = "hello";
   cout << str << endl;
   Wrapper wrapper(str);
   wrapper.str[0] = 'j'; // should change 'hello' to 'jello'
   cout << str << endl;
}
29
rcplusplus

Votre variable principale est std::string.

Votre variable de paramètre est const std::string&.

La constante dans les références est toujours "constante de bas niveau", ce qui signifie qu'elle modifie le type d'objet et non l'objet réel.

En revanche, une "constante de niveau supérieur" modifie un objet réel. Lisez C++ Primer on Top level const pour des éclaircissements.

Voici à quoi ressemble votre affectation lorsque vous passez des arguments:

const std::string& = std::str; //Values are ommited
// i.e const std::string newStr = std::string str

Vous initialisez un const type reference avec un non-const value ce qui est acceptable. Vous n'êtes pas censé modifier la valeur de std::string str en utilisant cette référence. Et, si vous essayez de changer la valeur de newStr à l'intérieur du constructeur, vous obtiendrez une erreur de compilation.

Ensuite, vous faites une autre affectation à l'intérieur du constructeur qui est également acceptable:

std::string = const std::string 

Le fait que wrap.str[0] n'a pas changé str de main est que, même si une référence a été utilisée pour instancier class str, class str a son propre objet et n'est pas lié à main str. L'utilisation de cette référence dans un paramètre lie simplement ce paramètre à main str; ne pas main str à class str.

Si vos variables de classe étaient référencées, cela aurait pu changer.

1
Jesus Christ