10

Foo **在什么情况下,您可能希望在 C++中使用多重间接(即,如 中的指针链)?

4

8 回答 8

12

@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;
}
于 2008-09-16T11:14:26.500 回答
7

IMO 最常见的用法是传递对指针变量的引用

void test(int ** var)
{
 ...
}

int *foo = ...
test(&foo);

您可以使用双指针创建多维锯齿状数组:

int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
于 2008-09-16T10:48:55.593 回答
5

一种常见的情况是您需要将指针传递给函数,并在该函数内对其进行初始化,并在函数外使用。如果没有多重间接,调用函数将永远无法访问已初始化的对象。

考虑以下函数:

initialize(foo* my_foo)
{
    my_foo = new Foo();
}

任何调用 'initialize(foo*)' 的函数都无法访问Foo的初始化实例,因为传递给该函数的指针是一个副本。(指针毕竟只是一个整数,整数是按值传递的。)

但是,如果函数是这样定义的:

initialize(foo** my_foo)
{
    *my_foo = new Foo();
}

......它被称为这样......

Foo* my_foo;

initialize(&my_foo);

...然后调用者将可以通过“my_foo”访问初始化的实例——因为它是传递给“initialize”的指针的地址

当然,在我的简化示例中,'initialize' 函数可以简单地通过 return 关键字返回新创建的实例,但这并不总是适合 - 也许该函数需要返回其他内容。

于 2008-09-16T11:06:33.133 回答
3

如果您将指针作为输出参数传递,您可能希望将其传递为Foo**并将其值设置为*ppFoo = pSomeOtherFoo.

在算法和数据结构部门,您可以使用这种双重间接来更新指针,这比交换实际对象的速度更快。

于 2008-09-16T10:50:04.607 回答
1

一个简单的例子是int** foo_mat用作二维整数数组。或者您也可以使用指向指针的指针 - 假设您有一个指针void* foo,并且您有 2 个不同的对象,这些对象具有以下成员对其的引用:void** foo_pointer1并且void** foo_pointer2,通过拥有指向指针的指针,您实际上可以检查是否*foo_pointer1 == NULL表明foo 为 NULL。如果 foo_pointer1 是常规指针,您将无法检查 foo 是否为 NULL。我希望我的解释不会太混乱:)

于 2008-09-16T10:51:29.860 回答
1

通常当您将指向函数的指针作为返回值传递时:

ErrorCode AllocateObject (void **object);

其中函数返回成功/失败错误代码并使用指向新对象的指针填充对象参数:

*object = new Object;

这在 Win32 的 COM 编程中被大量使用。

这更像是 C 要做的事情,在 C++ 中,您通常可以将这种类型的系统包装到一个类中,以使代码更具可读性。

于 2008-09-16T10:51:47.553 回答
1

卡尔:你的例子应该是:

*p = x;

(你有两颗星。):-)

于 2008-09-16T10:54:07.810 回答
1

在 C 中,成语是绝对需要的。考虑您希望函数将字符串(纯 C,因此是 char *)添加到指向 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);
于 2008-09-16T15:10:13.483 回答