C ++에서 참조로 포인터를 전달하는 이유? 어떤 상황에서

어떤 상황에서 C ++에서 이러한 성격의 코드를 사용하고 싶습니까?

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

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


답변

포인터가 가리키는 개체가 아닌 포인터를 수정해야하는 경우 참조로 포인터를 전달하는 것이 좋습니다.

이것은 이중 포인터가 사용되는 이유와 유사합니다. 포인터에 대한 참조를 사용하는 것이 포인터를 사용하는 것보다 약간 더 안전합니다.


답변

C ++ 프로그래머의 50 %는 삭제 후 포인터를 null로 설정하는 것을 좋아합니다.

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

참조가 없으면 호출자에게 영향을주지 않고 포인터의 로컬 복사본 만 변경합니다.


답변

David의 대답은 맞지만 여전히 약간 추상적 인 경우 두 가지 예가 있습니다.

  1. 메모리 문제를 더 일찍 발견하기 위해 해제 된 모든 포인터를 제로화 할 수 있습니다. C 스타일 :

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

    C ++에서 동일한 작업을 수행하려면 다음을 수행 할 수 있습니다.

    template<class T> void freeAndZero(T* &ptr)
    {
        delete ptr;
        ptr = 0;
    }
    
    int* ptr = new int;
    
    ...
    
    freeAndZero(ptr);
  2. 연결 목록을 다룰 때-종종 단순히 다음 노드에 대한 포인터로 표시됩니다.

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

    이 경우 빈 목록에 삽입 할 때 결과가 NULL더 이상 포인터 가 아니므로 들어오는 포인터를 반드시 변경해야합니다 . 이것은 함수에서 외부 포인터를 수정하여 서명에 포인터에 대한 참조를 포함하는 경우입니다.

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

이 질문에 예가 있습니다 .


답변

전달 된 포인터에 메모리를 할당하고 크기를 반환하는 함수를 제공하기 위해 이와 같은 코드를 사용해야했습니다. 내 회사가 STL을 사용하여 나에게 “객체”를 제공하기 때문입니다.

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

좋지는 않지만 포인터는 참조로 전달되어야합니다 (또는 이중 포인터 사용). 그렇지 않은 경우, 메모리 누수가 발생하는 값으로 전달되면 메모리가 포인터의 로컬 사본에 할당됩니다.


답변

한 가지 예는 파서 함수를 작성하고 읽을 소스 포인터를 전달하는 경우입니다. 함수가 파서가 올바르게 인식 한 마지막 문자 뒤에 해당 포인터를 앞으로 밀어 넣어야하는 경우입니다. 포인터에 대한 참조를 사용하면 함수가 원래 포인터를 이동하여 위치를 업데이트 함을 분명히 알 수 있습니다.

일반적으로 포인터를 함수에 전달 하고 원본에 영향을주지 않고 복사본을 이동하는 대신 원본 포인터를 다른 위치 로 이동 시키려면 포인터에 대한 참조를 사용 합니다.


답변

이것이 필요할 수있는 또 다른 상황은 포인터의 stl 컬렉션이 있고 stl 알고리즘을 사용하여 변경하려는 경우입니다. c ++ 98에서 for_each의 예.

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) 시그니처를 사용하면 원본이 아닌 포인터의 복사본이 있습니다.