문제
어떤 상황에서 다중 간접 참조(즉, 다음과 같은 포인터 체인)를 사용하고 싶을 수 있습니다. Foo **
) C++에서?
해결책
@aku가 지적한 가장 일반적인 사용법은 함수가 반환된 후 포인터 매개 변수에 대한 변경 사항이 표시되도록 허용하는 것입니다.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
이것은 인쇄됩니다
12
그러나 다음 예제와 같이 문자열 배열을 반복하고 이를 표준 출력으로 인쇄하는 몇 가지 다른 유용한 사용법이 있습니다.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
다른 팁
IMO의 가장 일반적인 사용법은 포인터 변수에 대한 참조를 전달하는 것입니다.
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
이중 포인터를 사용하여 다차원 가변 배열을 만들 수 있습니다.
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
일반적인 시나리오 중 하나는 없는 함수에 대한 포인터를 지정하고 해당 함수 내에서 초기화하고 함수 외부에서 사용하도록 합니다.다중 간접 참조가 없으면 호출 함수는 초기화된 개체에 액세스할 수 없습니다.
다음 기능을 고려하십시오.
initialize(foo* my_foo)
{
my_foo = new Foo();
}
'initialize(foo*)'를 호출하는 모든 함수는 초기화된 인스턴스에 액세스할 수 없습니다. 푸, 이 함수에 전달된 포인터가 복사본이기 때문입니다.(포인터는 결국 정수일 뿐이며 정수는 값으로 전달됩니다.)
그러나 함수가 다음과 같이 정의된 경우:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...이렇게 불렸어요...
Foo* my_foo;
initialize(&my_foo);
...그러면 호출자는 'my_foo'를 통해 초기화된 인스턴스에 액세스할 수 있습니다. 주소 '초기화'에 전달된 포인터입니다.
물론, 단순화된 예에서 'initialize' 함수는 return 키워드를 통해 새로 생성된 인스턴스를 간단히 반환할 수 있지만 항상 적합한 것은 아닙니다. 아마도 함수가 다른 것을 반환해야 할 수도 있습니다.
출력 매개변수로 포인터를 전달하는 경우 다음과 같이 전달할 수 있습니다. Foo**
그 값을 다음과 같이 설정하십시오. *ppFoo = pSomeOtherFoo
.
그리고 알고리즘 및 데이터 구조 부서에서는 이중 간접 참조를 사용하여 포인터를 업데이트할 수 있습니다. 이는 실제 객체를 교환하는 것보다 더 빠를 수 있습니다.
간단한 예는 다음과 같습니다. int** foo_mat
정수의 2차원 배열로.또는 포인터에 대한 포인터를 사용할 수도 있습니다. 포인터가 있다고 가정해 보겠습니다. void* foo
다음 멤버와 함께 참조가 있는 2개의 서로 다른 개체가 있습니다. void** foo_pointer1
그리고 void** foo_pointer2
, 포인터에 대한 포인터를 가짐으로써 실제로 다음을 확인할 수 있습니다. *foo_pointer1 == NULL
이는 foo가 NULL임을 나타냅니다.foo_pointer1이 일반 포인터인 경우 foo가 NULL인지 확인할 수 없습니다.제 설명이 너무 지저분하지 않았으면 좋겠어요 :)
칼:귀하의 예는 다음과 같아야 합니다:
*p = x;
(별이 두 개 있습니다.) :-)
C에서는 관용구가 절대적으로 필요합니다.char *에 대한 포인터 배열에 문자열(순수 C이므로 char *)을 추가하는 함수가 필요한 문제를 생각해 보세요.함수 프로토타입에는 세 가지 수준의 간접 참조가 필요합니다.
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
우리는 그것을 다음과 같이 부릅니다:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
C++에는 대신 참조를 사용하여 다른 서명을 생성하는 옵션이 있습니다.그러나 원래 질문에서 요청한 두 가지 수준의 간접 참조가 여전히 필요합니다.
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
일반적으로 함수에 대한 포인터를 반환 값으로 전달할 때:
ErrorCode AllocateObject (void **object);
여기서 함수는 성공/실패 오류 코드를 반환하고 새 객체에 대한 포인터로 객체 매개변수를 채웁니다.
*object = new Object;
이는 Win32의 COM 프로그래밍에서 많이 사용됩니다.
이는 C에서 수행하는 작업에 가깝습니다. C++에서는 이러한 유형의 시스템을 클래스로 래핑하여 코드를 더 읽기 쉽게 만들 수 있습니다.