将指针传递给指向函数的指针

pass pointers to pointers to function

我想写一个函数,它接受两个指针并将一个指针设置为另一个指向的位置。

我的第一次尝试是这样的:

void func(int* i1, int* i2)
{
    i2 = i1;
}

然后我意识到,我在这里传递指针地址并将一个指针的地址设置为另一个指针的地址。 像这样调用此函数会导致段错误:

int * int_ptr_1;
int * int_ptr_2 = nullptr;

int a = 5;

int_ptr_1 = &a;

func(int_ptr_1, int_ptr_2);

std::cout << *int_ptr_2 << std::endl;

但实际上为什么呢?如果 int_ptr_2 的地址现在与 int_ptr_1 的地址相同,为什么取消引用 int_ptr_2 不会产生 5 那么... int_ptr_1 指向 a,其值为 5...

这里和这样做有什么不同?:

int * int_ptr_1;
int * int_ptr_2;

int a = 5;

int_ptr_1 = &a;
int_ptr_2 = int_ptr_1;

效果很好...

通过研究,我发现您可以改为这样做:

void func(int*& i1, int*& i2)
{
    i2 = i1;
}

这会做我想做的事...但是...它的语义是什么?

void func(int* i1, int* i2)
{
    i2 = i1;
}

在这里,您按值传递两个指针并将第一个指针分配给第二个指针。变量 i1i2 的范围是 func 并且修改这些指针不会影响 func.

之外的任何内容
void func(int*& i1, int*& i2)
{
    i2 = i1;
}

这里的指针是按引用传递的,所以对它们的修改会影响传入的变量。

起初考虑按值和引用传递指针似乎违反直觉,但这完全等同于传递,比方说,int

void func(int i1, int i2)
{
    i2 = i1; //change only affects func
}

void func(int& i1, int& i2)
{
    i2 = i1; //change affects variables passed in
}

请注意,您不需要引用 i1,因为您不会对其进行修改。通常最好按值传递内置类型。您也可以将其标记为 const 以防止您犯下愚蠢的错误:

void func(int* const i1, int*& i2)
{
    i2 = i1;
}

您刚刚将指针内容按值传递给您的函数 func。这意味着您在 func 中所做的一切都不会影响外界,而只是修改传递给 func 的(临时)值。相反

void func (int** p1, int** p2)
{
    *p2 = *p1;
}

就可以了。你会这样称呼它

func (&int_ptr_1, &int_ptr_2);

来自您的主要功能。或者,您可以传递一个指针引用,正如您已经描述的那样。在那种情况下,同样的事情在幕后发生:编译器将一个地址传递给一个指针,并记住每次您使用该变量时,它都必须取消引用该地址。所以传递指针到指针是一种语法技巧。两种方式各有优势:

int** 方法在调用时明确表示允许 func 修改您的指针。 (这就是为什么在这种情况下我更喜欢它)。

int*&方法更容易使用。我会将它用于迭代器之类的东西。

[已添加] 作为对您的函数用户的额外帮助,我将按值设置第一个参数,这表明它是只读的:

void func (int* p1, int** pp2)
{
    *pp2 = p1;
}

你会这样称呼它:

func (int_ptr_1, &int_ptr_2);

看!现在乍一看,int_ptr_1 只是按值传递,在 func 内部没有更改,并且 int_ptr_2 是输出参数。如果您在整个代码中使用此范例,您将看到它会变得多么清晰和易于审查。

希望能帮助您澄清事情。