有人可以解释在 C++ 中通过指针传递和通过引用传递的目的是啥吗?

Posted

技术标签:

【中文标题】有人可以解释在 C++ 中通过指针传递和通过引用传递的目的是啥吗?【英文标题】:Can someone explain what purpose passing by pointer and passing by reference have in c++?有人可以解释在 C++ 中通过指针传递和通过引用传递的目的是什么吗? 【发布时间】:2019-12-15 07:49:33 【问题描述】:

我只是不明白为什么要使用它们而不是变量。

例如,有人可以解释为什么这不起作用:

void swap(int x, int y) 
  int z = x;
  x = y;
  y = z;


int main() 
  int x, y;
  x = 5, y = 4;
  swap(x, y);
  cout << x << " " << y;

但这确实:

void swap(int *x, int *y) 
  int z = *x;
  *x = *y;
  *y = z;


int main() 
  int x, y;
  x = 5, y = 4;
  swap(&x, &y);
  cout << x << " " << y;

【问题讨论】:

【参考方案1】:

在您给您的第一个示例中,您通过值传递参数,这会在内存中创建变量的副本,并且函数对副本进行操作。这意味着 x 和 y 的原始值不会被修改,只有它们的副本会被修改。当函数结束时,副本被销毁,原始值保持不变。

在第二个示例中,您传入一个指针,该指针只是“指向”存储变量 x 和 y 的内存。当您取消引用(* 运算符)指针时,您可以像使用其他任何变量一样使用该变量,这意味着这样做:

*x = *y;

您实际上是将内存地址 x 处的变量设置为内存地址 y 处变量的值。与第一个代码 sn-p 不同,这会全局更改变量的值。

简而言之,按值传递会创建 x 的副本供您使用。函数完成后 x 被销毁,原始 x 变量保持不变。通过指针或引用传递意味着您传入 x 的存储位置,然后访问 x 变量。当函数结束时,x 仍然被修改。

它们为什么存在? 简而言之,将指针传递给大型对象很有用,因为创建具有大量内存占用的类或结构的副本真的很慢。

什么时候应该传值 当您只想要数据的副本而不修改原始数据时,通常是因为修改原始数据是不必要的或对应用程序有害。

什么时候应该通过引用传递 当你想修改函数内变量的原始值时。

什么时候应该使用指针? 当您想修改内存中的变量或为该内存地址分配一个全新的变量时。

【讨论】:

【参考方案2】:

我将分两部分回答这个问题。

首先,为什么这两对代码的行为不同。这很简单。当您调用函数并通过引用传递或使用指针时,该函数正在查看变量的内存位置,然后修改这些内存位置的内容。因此,当您对变量(或交换变量)进行更改时,该更改将在函数调用之外可见。

在第一组代码中,您传递给函数的 int 值实际上被复制到仅在函数内部定义的新临时变量中。所以该函数使用相同的数字,但是当它修改它们时,修改只针对那些复制的变量,而不是原始变量。

那么,为什么要通过引用传递。我通常在我的代码中通过引用传递的主要原因是它更快。如果你将一个大对象传递给一个函数,你不想复制所有的数据。 (当然,对于大多数代码而言,这种速度可能可以忽略不计,但节省时间并没有什么坏处。)您关心的另一个原因是,正如您在此处看到的那样,当您想要更改对象并进行这些更改时反映在函数之外。

另一方面,如果您想对对象进行更改但不影响原始对象,则不希望通过引用传递。例如,如果您有一个对向量执行 argsort 的函数,并且 argsort 的实现也对向量进行了排序。您不想实际修改向量,如果您通过引用传递它会这样做。但是,如果您通常将向量传递给函数,它只会将该向量复制到一个新的临时变量中并对该变量进行排序,而不会改变初始向量。

另外,请注意某些语言,例如 python(我认为是 Java)总是通过引用传递。

【讨论】:

Also, be warned that some languages such as python (and I think Java) always pass by reference. 这不是真的,至少对于 C++ 中如何定义 "passed-by-reference" 来说不是这样。如果你有一个def get_string(the_string): the_string = 'something' 并且你有get_string(val),那么val 将不会持有something。在 Python、Java、javascript 中,它是 “按值传递”,但传递的值是引用(不可变基元除外)。所以从 c++ 的角度来看,Python、Java、JS,... 做一个 "pass-by-reference-copy""pass-by-value-copy" .

以上是关于有人可以解释在 C++ 中通过指针传递和通过引用传递的目的是啥吗?的主要内容,如果未能解决你的问题,请参考以下文章

在C中通过命令行传递整数?

在函数c ++中通过引用传递的指针参数

在 C++ 中通过引用和值传递字符串

C++ 11 可以在不同线程中通过引用安全地传递和访问 std::atomics

在 C++ 中通过指针捕获异常

在 C++ 中通过引用传递 char 的效率