web-dev-qa-db-fra.com

Raison de passer un pointeur par référence en C ++?

Dans quelles circonstances voudriez-vous utiliser un code de cette nature en c ++?

void foo(type *&in) {...}

void fii() {
  type *choochoo;
  ...
  foo(choochoo);
}
86
Matthew Hoggan

Si vous avez besoin de modifier le pointeur plutôt que l'objet sur lequel il pointe, vous souhaitez passer un pointeur par référence.

Ceci est similaire à la raison pour laquelle les pointeurs doubles sont utilisés; L'utilisation d'une référence à un pointeur est légèrement plus sûre que l'utilisation de pointeurs.

131
David Z.

50% des programmeurs C++ aiment définir leurs pointeurs sur null après une suppression:

template<typename T>    
void moronic_delete(T*& p)
{
    delete p;
    p = nullptr;
}

Sans la référence, vous ne modifieriez qu'une copie locale du pointeur, sans affecter l'appelant.

62
fredoverflow

La réponse de David est correcte, mais si cela reste un peu abstrait, voici deux exemples:

  1. Vous voudrez peut-être supprimer tous les pointeurs libérés pour résoudre les problèmes de mémoire plus tôt. C-style que vous feriez:

    void freeAndZero(void** ptr)
    {
        free(*ptr);
        *ptr = 0;
    }
    
    void* ptr = malloc(...);
    
    ...
    
    freeAndZero(&ptr);
    

    En C++, pour faire la même chose, vous pourriez faire:

    template<class T> void freeAndZero(T* &ptr)
    {
        delete ptr;
        ptr = 0;
    }
    
    int* ptr = new int;
    
    ...
    
    freeAndZero(ptr);
    
  2. Lorsqu'il s'agit de listes chaînées - souvent simplement représentés comme des pointeurs vers un nœud suivant:

    struct Node
    {
        value_t value;
        Node* next;
    };
    

    Dans ce cas, lorsque vous insérez dans la liste vide, vous devez nécessairement changer le pointeur entrant car le résultat n'est plus le pointeur NULL. C'est un cas où vous modifiez un pointeur externe à partir d'une fonction, de sorte qu'il aurait une référence à un pointeur dans sa signature:

    void insert(Node* &list)
    {
        ...
        if(!list) list = new Node(...);
        ...
    }
    

Il y a un exemple dans cette question .

14
Antoine

J'ai dû utiliser un code tel que celui-ci pour fournir des fonctions permettant d'allouer de la mémoire à un pointeur transmis et de me retourner sa taille car mon entreprise "m'objet" à l'aide de la STL

 int iSizeOfArray(int* &piArray) {
    piArray = new int[iNumberOfElements];
    ...
    return iNumberOfElements;
 }

Ce n'est pas Nice, mais le pointeur doit être passé par référence (ou utiliser un double pointeur). Sinon, la mémoire est allouée à une copie locale du pointeur si elle est passée par valeur, ce qui entraîne une fuite de mémoire.

7
mathematician1975

Par exemple, lorsque vous écrivez une fonction d'analyse et lui passez un pointeur source à lire, si la fonction est supposée pousser ce pointeur en arrière du dernier caractère correctement reconnu par l'analyseur. L'utilisation d'une référence à un pointeur indique clairement que la fonction déplace le pointeur d'origine pour mettre à jour sa position.

En général, vous utilisez des références à des pointeurs si vous souhaitez passer un pointeur sur une fonction et le laisser déplacer ce pointeur original à un autre emplacement au lieu de simplement en déplacer une copie sans affecter l'original.

2
BarbaraKwarc

Une autre situation où vous pourriez en avoir besoin est si vous avez une collection stl de pointeurs et souhaitez les modifier à l'aide de l'algorithme stl. Exemple de for_each en c ++ 98.

struct Storage {
  typedef std::list<Object*> ObjectList;
  ObjectList objects;

  void change() {
    typedef void (*ChangeFunctionType)(Object*&);
    std::for_each<ObjectList::iterator, ChangeFunctionType>
                 (objects.begin(), objects.end(), &Storage::changeObject);
  }

  static void changeObject(Object*& item) {
    delete item;
    item = 0;
    if (someCondition) item = new Object();
  } 

};

Sinon, si vous utilisez changeObject (objet * élément) la signature que vous avez copie du pointeur, pas l'original.

0
Nine