何时在C++中将指向指针的指针作为参数传递给函数?

4

这里我读了一篇关于何时将指针作为函数参数传递的文章。但我想知道在哪些情况下应该将指向指针的指针作为函数参数传递。

更明确地说,我想知道何时应该使用类似以下代码:

func(int **x);

2
当您需要更改指针参数时,例如 int alloc_my_object(my_object **ob1)。基本上,如果您有一个需要更改的参数,则将其作为指针传递进去。如果参数类型已经是指针,则会传入“指向指针”的指针。 - amdixon
3
为什么你不使用引用传递指针,而要这样做呢? - Angew is no longer proud of SO
最好再读一些文章,那篇文章的前提是错误的,例如“使用引用传递大对象”。这只是过早优化,并不是传递引用的好理由。你应该根据你要对对象做什么来选择如何传递对象,而通过指针传递几乎从来不是你真正需要的。https://dev59.com/lWUp5IYBdhLWcg3wAjtF#15600615 https://dev59.com/qHVC5IYBdhLWcg3whBaj#271344 - stijn
1
您的标题提到了C++,但是您同时标记了C++C。两者在这方面有很大的区别;您真的希望获得关于两者的答案吗? - Angew is no longer proud of SO
@Angew 不,将其标记为C是个错误。我想了解关于C++的内容。 - Nejat
2
太棒了,现在大部分的答案都很糟糕。 - juanchopanza
6个回答

11
void SomeFun1(int *);
void SomeFun2(int **);
int i;
int *ptr = &i;

//when you want value of ptr should remain unchanged, but you want to change only value of i, use,
SomeFun1(int *)

//when you want value of ptr should change. i.e, it should point to some other memory other than i, use,
SomeFun2(int **);

2
在每种情况下,我应该如何调用每个函数? 分别是 somefun1(ptr) 和 somefun2(&ptr) ? - EmiliOrtega

8

C++

在C++中,您可以通过引用传递参数,当您希望对参数进行修改并影响调用者传递的参数时,就需要这样做。也就是说,通过引用传递表示输出或输入/输出参数。

如果函数需要指针(显然),或者您想要表示可选的输出参数-因为引用必须始终绑定到某个东西,但指针可以为null,则应传递指针。

按照同样的逻辑,如果函数实际上需要双重指针(在C ++中非常罕见),或者如果您想要表示指针类型的可选[输入]输出参数(也很少见),则传递指针指针。

下面是一些示例(虽然构造的,但应该能够说明问题):

int square(int x)  //pass int by value
{ return x * x; }

void squareRoots(double in, double &plus, double &minus)  //pass double by reference
{
  plus = sqrt(in);
  minus = -plus;
}

int toNumber(String s, bool *ok = nullptr)  //optional out parameter
{
  try {
    int val = s.toNumber();
    if (ok)
      *ok = true;
    return val;
  } catch (NotANumber &) {
    if (ok)
      *ok = false;
    return 0;
  }
}

int computeAge(Person *person)  //pass pointer by value
{
  if (!person)
    return -1;
  else
    return now() - person->dateOfBirth();
}

bool createPerson(Person * &person)  //pass pointer by reference
{
  if (tooManyPeople())
    return false;
  person = new Person();
  return true;
}

int sum(int **values)  //pass double pointer by value
{
  if (!values)
    return 0;
  int res = 0;
  while (*values) {
    res += **values;
    ++values;
  }
  return res;
}

bool allocate(int ** &arr)  //pass double pointer by reference
{
  if (!enoughMemory())
    return false;
  arr = new int*[1024];  // array of 1024 pointers to int
  return true;
}

bool newNode(Node **node = nullptr)  //optional out parameter
{
  Node *added = dataStructure.createNode();
  if (node)
    *node = added;
  return added;
}

(注1:我这里只谈论非const引用,因为这与通过指针和通过引用传递有关。通过const引用传递通常意味着“对象太大,不要无谓地复制”,但当涉及到指向指针的指针时并不适用。)
(注2:上述示例非常糟糕,因为它们使用了拥有原始指针、动态数组分配等内容。在实际的C++中,你应该使用智能指针、std::vector等代替。这就是为什么C++中指向指针很少见的原因。)

C

在C中,双指针更常见,因为C没有引用类型。因此,你也使用指针来“按引用传递”。在上面的C++示例中,&在参数类型中使用时,C中会使用*(并在操作参数时对其进行解引用)。以下是一个示例:

void squareRoots(double in, double *plus, double *minus)  //pass double "by reference"
{
  *plus = sqrt(in);
  *minus = -*plus;
}

8
当您希望函数设置指针的值时,可以将指向指针的指针作为参数传递。通常在函数需要分配内存(通过malloc或new)并将该值设置为参数时使用此方法,然后调用者将负责释放它。与作为函数返回值返回它相比,这样做更好,因为调用者不会错误地忽略返回值而导致泄漏。如果要返回多个值,也可以使用此方法。
另一个使用此方法的原因是当您希望可选地返回值时(即指向指针可以为NULL)。例如,看一下strtol(),它有一个可选的endptr。
注意:永远不要将此指针设置为堆栈变量。

4
  • 当您想传递指针数组时,应使用<type>**

例子:

int main(int argc, char **argv) {   // argv is an array of char*
  • 如果你想更改指针地址(在C ++中,你可以传递指针引用),你也会使用它。

3
还没有提到的是动态分配二维数组-实际上,你会有一个指向其他指针的指针数组。

0
这可能是我的观点。但是,当您期望使用NULL作为完美值时(例如在链接列表中),应该使用指针来引用变量。 当您不希望将值初始化为NULL时,应使用引用。 否则,引用和指针在许多方面都是相似的。您可以从函数内部更改指针或按引用参数的值。它们都是多态的。...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接