首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么基于指针交换两个值不能在函数作用域之外工作?

为什么基于指针交换两个值不能在函数作用域之外工作?
EN

Stack Overflow用户
提问于 2012-11-09 01:52:14
回答 8查看 3.4K关注 0票数 10

我已经很多年没有用C++编程了,所以我决定在指针上重温一下我的记忆。

在两个数字之间交换的经典示例中,示例如下

代码语言:javascript
运行
复制
void swapPointersClassic(double *num1, double *num2) 
{
  double temp;
  temp = *num1;
  *num1 = *num2;
  *num2 = temp;
}

这允许我们像swapPointersClassic(&foo, &bar);一样进行函数调用,因为我们传入了变量foo和bar的内存地址,函数将检索这些值并进行交换。但我开始想,为什么我不能这样做呢?

代码语言:javascript
运行
复制
void swapPointers(double *num1, double *num2)
{
  double *temp;
  temp = num1;
  num1 = num2;
  num2 = temp;
}

这对我来说似乎更有意义,因为我们只需要创建足够的临时存储空间来存储内存地址num1 (而不是一个完整的临时存储空间来存储双精度值*num1)。然而,似乎函数作用域限制了指针交换的效果。在调用swapPointers(&foo, &bar);之后,我可以看到在函数swapPointers中,foo和bar确实被交换了。一旦我们退出swapPointers函数,foo和bar就不再交换。有没有人能告诉我为什么会这样?这个行为让我想起了典型的按值传递方法,但我们这里是通过指针传递的。所以这意味着我们只能触摸这些指针所指向的值,而不是指针本身?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-11-09 01:58:25

事实上,你并不是真的通过指针来传递。通过值传递两个指针。传递指针本身是不够的-你必须取消对它们的引用。取消引用指针(副本)的行为使得魔术发生,并且它是实现作用域遍历的实际位置。

修改函数的参数是函数的局部操作,即使参数本身是指针也是如此。为了访问它们所指向的内存,必须取消对它们的引用(同样,“按指针传递”不仅仅是传递指针-它传递的是正确使用它们的指针)。

另外,请考虑以下几点。如果你的第二种方法起作用了,并且两个指针被交换了,那么就意味着变量的地址被交换了。这不太合理。

顺便说一下,在C++中,我们有一个真正的按引用传递的调用约定,所以不需要弄乱指针:

代码语言:javascript
运行
复制
void swap(double &a, double &b)
{
    double temp = a;
    a = b;
    b = temp;
}

float a = 1, b = 2;
swap(a, b);

(这只是一个实现问题,编译器很可能会通过实际使用指针来实现此行为,但至少您不会感到头疼。)

票数 8
EN

Stack Overflow用户

发布于 2012-11-09 01:55:36

如果你想交换指针,而不是它们的值,你需要传递指针的指针:

代码语言:javascript
运行
复制
void swapPointers(double** num1, double** num2)
{
  double* temp = *num1;
  *num1 = *num2;
  *num2 = temp;
}

您可以在http://ideone.com/iklCta中看到一个示例

您甚至可以使用引用:

代码语言:javascript
运行
复制
void swapPointers(double*& num1, double*& num2) {
  double* temp = num1;
  num1 = num2;
  num2 = temp;
}

示例:http://ideone.com/w4k9mV

当您处理大型对象(例如:图像数据),并且您不想移动大量内存,而只想移动引用时,这是很有用的。

票数 6
EN

Stack Overflow用户

发布于 2012-11-09 02:30:44

这是一个很好的问题,但是一旦你弄清楚了,请使用std::swapstd::iter_swap,而不是编写你自己的。

如果foobar是指针,则调用std::swap(foo, bar)将在这两个指针之间交换地址。调用std::swap(*foo, *bar)std::iter_swap(foo, bar)将取消对指针的引用,并交换指针所指向的对象。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13294823

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档