Подтвердить что ты не робот

Причина передачи указателя по ссылке в С++?

В каких обстоятельствах вы хотели бы использовать код такого типа в С++?

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

void fii() {
  type *choochoo;
  ...
  foo(choochoo);
}
4b9b3361

Ответ 1

Вы хотите передать указатель по ссылке, если вам нужно изменить указатель, а не объект, на который указывает указатель.

Это похоже на то, почему используются двойные указатели; использование ссылки на указатель немного безопаснее, чем использование указателей.

Ответ 2

50% программистов на С++ любят устанавливать свои указатели на нуль после удаления:

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

Без ссылки вы будете менять локальную копию указателя, не влияя на вызывающего.

Ответ 3

Ответ Дэвида правильный, но если он еще немного абстрактный, вот два примера:

  • Вам может потребоваться сбросить все освобожденные указатели, чтобы уловить проблемы памяти раньше. C-стиль, который вы сделали бы:

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

    В С++, чтобы сделать то же самое, вы можете сделать:

    template<class T> void freeAndZero(T* &ptr)
    {
        delete ptr;
        ptr = 0;
    }
    
    int* ptr = new int;
    
    ...
    
    freeAndZero(ptr);
    
  • При работе со связанными списками - часто просто представляются в виде указателей на следующий node:

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

    В этом случае, когда вы вставляете в пустой список, вы обязательно должны изменить входящий указатель, потому что результат больше не является указателем NULL. Это случай, когда вы изменяете внешний указатель из функции, поэтому он имеет ссылку на указатель в своей сигнатуре:

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

Вот пример в этот вопрос.

Ответ 4

Мне пришлось использовать такой код, чтобы предоставить функции для распределения памяти на переданный указатель и вернуть его размер, потому что моя компания "объект" мне использует STL

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

Это не хорошо, но указатель должен быть передан по ссылке (или использовать двойной указатель). Если нет, память выделяется локальной копии указателя, если она передается по значению, что приводит к утечке памяти.

Ответ 5

Другая ситуация, когда вам может понадобиться, - это если у вас есть stl-коллекция указателей и вы хотите изменить они используют алгоритм stl. Пример for_each в С++ 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();
  } 

};

В противном случае, если вы используете подпись changeObject (Object * item), у вас есть копия указателя, а не оригинала.

Ответ 6

Один пример - когда вы пишете функцию парсера и передаете ему указатель источника для чтения, если функция должна нажимать этот указатель вперед за последним символом, который был правильно распознан парсером. Использование ссылки на указатель дает понять, что функция будет перемещать исходный указатель, чтобы обновить его положение.

В общем, вы используете ссылки на указатели, если хотите передать указатель на функцию и позволить ему перенести этот исходный указатель на другую позицию вместо того, чтобы просто скопировать его, не затрагивая оригинал.