Question

Les références en C ++ sont une construction conventionnelle qui nous permet de simplifier le code C suivant:

f(object *p){
  //do something
}

int main(){
  object* p = (object*) calloc(sizeof(object));
  f(p);
}

à

f(object& o){
  //do something
}

int main(){
  object o = object();
  f(o);
}

Les pointeurs partagés sont un autre avantage en C ++ qui simplifient la gestion de la mémoire. Cependant, je ne suis pas sûr de savoir comment passer un shared_ptr à une fonction telle que f (object & o) qui accepte les arguments par référence?

f(object& o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(*p);
}

Le pointeur partagé sera-t-il incrémenté lorsque son objet sera transmis par référence à une fonction?

Était-ce utile?

La solution

Prenez un shared_ptr par valeur et le nombre de références augmentera. C’est plus facile lorsque vous saisissez :

typedef boost:shared_ptr<object> object_ptr;

void foo(object_ptr obj)
{
    obj->/* stuff*/;
    obj.reset(); //only resets this local copy, that means:
                 // reduce reference count (back to 1), and
                 // set obj to point at null.
}

int main(void)
{
    object_ptr obj(new object());
    foo(obj);
}

N'oubliez pas que les références sont des alias. Lorsque vous passez par référence, vous ne passez pas de pointeurs, de copies, etc., vous aliasez un autre objet. (En réalité, ils sont implémentés comme des pointeurs):

typedef boost:shared_ptr<object> object_ptr;

void foo(object_ptr& obj)
{
    obj.reset(); // the references was never increased, since a copy has not
                 // been made, this *is* obj in main. so the reference 
                 // goes to 0, and obj is deleted
}

int main(void)
{
    object_ptr obj(new object);
    foo(obj); // after this, obj has been reset!
}

N'oubliez jamais d'être const correct pour éviter les erreurs:

typedef boost:shared_ptr<object> object_ptr;

void foo(const object_ptr& obj)
{
    obj.reset(); // cannot do! 
}

int main(void)
{
    object_ptr obj(new object);
    foo(obj);
}

Je pense que vous devriez préférer utiliser des pointeurs intelligents comme références, lorsque cela est possible, afin d'éviter des incréments et des décréments superflus (et des copies ou autres).

Autres conseils

  

Le pointeur partagé sera-t-il incrémenté lorsque son objet sera transmis par référence à une fonction?

Non, car vous accédez au pointeur brut, puis vous le passez. Vous voulez faire quelque chose de semblable à ceci:

f(shared_ptr<object> o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(p);
}
f(object& o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(*p);
}
     

Le pointeur partagé sera-t-il incrémenté?   quand son objet est passé par référence   à une fonction?

Dans le code ci-dessus - non. p aura son compteur de référence égal à 1 à tout moment. Vous pouvez le vérifier dans un débogueur. Le compteur de références shared_ptr compte le nombre d'occurrences shared_ptr qui pointent sur le même objet. Il ne suit pas les références que vous créez en appelant l'opérateur * (). Et cela n’est pas obligé - puisque p est assuré de vivre jusqu’à la fin de l’étendue et que l’appel de la fonction est dans cette même étendue (ou plus profondément), p sera pendant tout l'appel à f (). Donc tout va bien.

... sauf dans f , vous prenez l'adresse de o et vous stockez un emplacement qui durera après le retour de f . C’est ce que vous devriez éviter à tout prix - passez le shared_ptr si vous avez besoin de le faire.

Tout d’abord, d’un point de vue fonctionnel, les références en C ++ sont exactement les mêmes que les pointeurs. La seule raison pour laquelle ils ont été ajoutés au langage a été de rendre la syntaxe de surcharge des opérateurs plus naturelle. (Par exemple, pour permettre à un utilisateur d'écrire a + b au lieu de & amp; a + & amp; b)

Vos exemples de code C et C ++ ne sont absolument pas équivalents. La version C de votre code C ++ serait:

f(object *p){
  //do something
}

int main(){
  object o;
  object_constructor(&o);
  f(&o);
  object_destructor(&o);
}

En fait, il s'agit du type de code que votre compilateur C ++ générera de manière conceptuelle.

En ce qui concerne votre deuxième question: oui, c’est la bonne façon d’appeler la fonction f. Le compteur de pointeur partagé ne sera pas incrémenté. Le pointeur réel sur l'objet sera transmis, comme si vous n'utilisiez pas un shared_ptr. C'est sûr cependant, tant que f ne fait rien de génial. Rappelez-vous que la même chose se passe exactement comme si le paramètre de f prenait un pointeur au lieu d'une référence. La seule différence est que le compilateur transmet automatiquement l'adresse de la variable sans que vous ayez à utiliser explicitement l'option & amp; opérateur.

Personnellement, je n'aime pas toujours transmettre des variables par référence (passer par référence const est cependant correct). Je préfère utiliser un pointeur, car il est plus clair sur le site de l'appel que la fonction que nous appelons peut potentiellement modifier son argument (puisque le symbole & amp; est visible sur le site de l'appel).

Paix

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top