어떤 상황에서 C ++에서 이러한 성격의 코드를 사용하고 싶습니까?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
어떤 상황에서 C ++에서 이러한 성격의 코드를 사용하고 싶습니까?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
답변:
포인터가 가리키는 개체가 아닌 포인터를 수정해야하는 경우 참조로 포인터를 전달하는 것이 좋습니다.
이것은 이중 포인터가 사용되는 이유와 유사합니다. 포인터에 대한 참조를 사용하는 것이 포인터를 사용하는 것보다 약간 더 안전합니다.
delete
하거나 메모리의 다른 위치에 다시 바인딩 할 수 없다는 의미 입니까? 아니면 내가 틀렸습니까?
[]
운영자에게 과부하가 걸립니다. 이에 대한 가능한 (실제로 자연스러운) 서명 중 하나는 const T &operator[](size_t index) const
. 그러나 T &operator[](size_t index)
. 동시에 둘 다 가질 수 있습니다. 후자는 myArray[jj] = 42
. 동시에 데이터에 대한 포인터를 제공하지 않으므로 호출자가 메모리를 엉망으로 만들 수 없습니다 (예 : 실수로 삭제).
C ++ 프로그래머의 50 %는 삭제 후 포인터를 null로 설정하는 것을 좋아합니다.
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
참조가 없으면 호출자에게 영향을주지 않고 포인터의 로컬 복사본 만 변경합니다.
paranoid_delete
Puppy는 이름을 moronic_delete
. 그는 아마도 다른 50 %에 속할 것입니다;) 어쨌든 짧은 대답은 null after 설정 포인터 delete
가 거의 유용하지 않으며 (어쨌든 범위를 벗어나야하기 때문에) 종종 "사용 후 사용"버그의 탐지를 방해한다는 것입니다.
delete
일반적으로 어리석은 것 같습니다 . 강아지, 인터넷 검색을 좀 해봤는데, 삭제가 왜 완전히 쓸모가 없는지 알 수 없습니다. 조금 더 설명하거나 링크를 제공 할 수 있습니까?
David의 대답은 맞지만 여전히 약간 추상적 인 경우 두 가지 예가 있습니다.
메모리 문제를 더 일찍 발견하기 위해 해제 된 모든 포인터를 제로화 할 수 있습니다. 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);
연결 목록을 다룰 때-종종 단순히 다음 노드에 대한 포인터로 표시됩니다.
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) 시그니처를 사용하면 원본이 아닌 포인터의 복사본이 있습니다.