Powód, aby przekazać wskaźnik przez odniesienie w C++?

W jakich okolicznościach chciałbyś używać kodu tego typu w c++?

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

void fii() {
  type *choochoo;
  ...
  foo(choochoo);
}
Author: Matthew Hoggan, 2012-04-20

6 answers

Chcesz przekazać wskaźnik przez odniesienie, jeśli musisz zmodyfikować wskaźnik, a nie obiekt, do którego wskazuje wskaźnik.

Jest to podobne do tego, dlaczego używane są podwójne wskaźniki; użycie odniesienia do wskaźnika jest nieco bezpieczniejsze niż używanie wskaźników.

 119
Author: David Z.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-20 22:51:22

50% programistów C++ lubi ustawiać swoje wskaźniki NA null po usunięciu:

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

Bez referencji zmieniałbyś tylko lokalną kopię wskaźnika, nie wpływając na wywołującego.

 53
Author: fredoverflow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-10 19:06:45

Odpowiedź Dawida jest poprawna, ale jeśli nadal jest trochę abstrakcyjna, oto dwa przykłady:

  1. Możesz zerować wszystkie wolne wskaźniki, aby wcześniej wykryć problemy z pamięcią. C-style zrobiłbyś:

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

    W C++ aby zrobić to samo, możesz zrobić:

    template<class T> void freeAndZero(T* &ptr)
    {
        delete ptr;
        ptr = 0;
    }
    
    int* ptr = new int;
    
    ...
    
    freeAndZero(ptr);
    
  2. Gdy mamy do czynienia z linked-listami - często przedstawianymi po prostu jako wskaźniki do następnego węzła:

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

    W tym przypadku, po wstawieniu do pustej listy musisz koniecznie zmienić przychodzący wskaźnik ponieważ wynik nie jest już wskaźnikiem NULL. Jest to przypadek, w którym można zmodyfikować zewnętrzny wskaźnik z funkcji, tak aby miał odniesienie do wskaźnika w jego sygnaturze:

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

Jest przykład w to pytanie.

 14
Author: Antoine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:59

Musiałem użyć takiego kodu, aby zapewnić funkcje przydzielające pamięć do wskaźnika przekazanego i zwracające jej rozmiar, ponieważ moja firma "obiekt" do mnie za pomocą STL

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

To nie jest miłe, ale wskaźnik musi być przekazany przez odniesienie (lub użyć podwójnego wskaźnika). Jeśli nie, Pamięć jest przydzielana do lokalnej kopii wskaźnika, jeśli jest przekazywana przez wartość, co powoduje wyciek pamięci.

 7
Author: mathematician1975,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-21 08:18:09

Jednym z przykładów jest zapisanie funkcji parsera i przekazanie jej wskaźnika źródłowego do odczytu, jeśli funkcja ma przesunąć wskaźnik do przodu za ostatnim znakiem, który został poprawnie rozpoznany przez parser. Użycie odniesienia do wskaźnika wyjaśnia, że funkcja przesunie oryginalny wskaźnik, aby zaktualizować jego pozycję.

Ogólnie rzecz biorąc, używasz referencji do wskaźników, jeśli chcesz przekazać wskaźnik do funkcji i pozwolić jej przenieść oryginalny wskaĺşnik do innej pozycji zamiast po prostu przesuniÄ ™ Ä ‡ kopiÄ ™ bez wpĹ 'ywu na oryginaĹ'.

 1
Author: BarbaraKwarc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 01:17:56

Inna sytuacja, kiedy możesz tego potrzebować, to jeśli masz kolekcję wskaźników stl i chcesz zmienić używają algorytmu stl. Przykład for_each w 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();
  } 

};

W przeciwnym razie, jeśli użyjesz changeObject(Object* item) signature masz kopię wskaźnika, a nie oryginalną.

 0
Author: Nine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-25 08:37:19