通过引用传递时取消引用指针

时间:2012-07-05 15:03:24

标签: c++ pointers reference

当通过引用函数传递时取消引用指针会发生什么?

这是一个简单的例子

int& returnSame( int &example ) { return example; }

int main()
{
  int inum = 3;
  int *pinum = & inum;

  std::cout << "inum: " <<  returnSame(*pinum) << std::endl;

  return 0;          

}

是否有临时对象?

3 个答案:

答案 0 :(得分:35)

取消引用指针不会创建副本;它会创建一个引用指针目标的左值。这可以绑定到 lvalue 引用参数,因此该函数接收对指针指向的对象的引用,并返回对该引用的引用。此行为是明确定义的,不涉及临时对象。

如果按值获取参数,则会创建一个本地副本,并返回对该参数的引用,如果访问它则会产生未定义的行为。

答案 1 :(得分:27)

对您的问题的答案

不,此行为已定义。除非程序员明确指定,否则在取消引用指针类型或使用引用类型时不会调用构造函数,就像下面的代码片段一样,new运算符调用int类型的默认构造函数。 / p>

int* variable = new int;

至于实际发生的事情,正如所写,returnSame(*pinum)inum是同一个变量。如果您想亲自验证,可以使用以下代码段:

returnSame(*pinum) = 10;
std::cout << "inum: " << inum << std::endl;

进一步分析

我将首先更正您提供的代码,它在发布之前看起来并不像您尝试编译的那样。编辑后,剩下的一个错误出现在第一行:

int& returnSame( int &example ) { return example; } // semi instead of colon

指针和参考

编译器以相同的方式处理指针和引用,它们的使用不同,而不是它们的实现。指针类型和引用类型存储其他内容的 location 作为其值。指针解除引用(使用*->运算符)指示编译器生成代码以跟随指针并对其引用的位置执行操作,而不是值本身。取消引用指针时不会分配新数据(不调用构造函数)。

使用引用的工作方式大致相同,只是编译器会自动假定您希望该位置的值而不是位置本身。事实上,不可能以指针允许的相同方式引用引用指定的位置:一旦分配,引用就不能重新定位(更改)(即,不依赖于未定义的行为),但是您仍然可以使用&运算符来获取其值。甚至可以使用NULL引用,但处理这些引用特别棘手,我不建议使用它们。

摘录分析

int *pinum = & inum;

创建指向现有变量inum的指针。指针的值是存储inum的内存地址。创建和使用指针不会隐式调用指向对象的构造函数,EVER。这项任务留给程序员。

*pinum

取消引用指针会有效地生成常规变量。此变量在概念上可能占用与另一个命名变量使用的相同空间,或者可能不占用。在这种情况下,*pinuminum是同一个变量。当我说“产生”时,重要的是要注意,而不是调用构造函数。这就是为什么你必须在使用它们之前初始化指针:指针解除引用永远不会分配存储。

returnSame(*pinum)

此函数接受引用并返回相同的引用。有用的是要意识到这个函数也可以用指针编写,并且行为方式完全相同。引用也不执行任何初始化,因为它们不调用构造函数。但是,使用未初始化的引用是非法的,因此通过它们运行未初始化的内存并不像指针那样常见。可以通过以下方式重写您的函数以使用指针:

int* returnSamePointer( int *example ) { return example; }

在这种情况下,您无需在传递指针之前取消引用指针,但在打印之前需要取消引用该函数的返回值:

std::cout << "inum: " <<  *(returnSamePointer(pinum)) << std::endl;

NULL引用

声明NULL引用很危险,因为尝试使用它会自动尝试取消引用它,这将导致分段错误。但是,您可以安全地检查引用是否为空引用。同样,我强烈建议不要使用这些。

int& nullRef = *((int *) NULL);      // creates a reference to nothing
bool isRefNull = (&nullRef == NULL); // true

<强>摘要

  • 指针和引用类型是实现相同目标的两种不同方式
  • 适用于其中的大多数问题都适用于另一个
  • 在任何情况下,指针和引用都不会隐式调用构造函数或析构函数
  • 只要指针被正确初始化,声明对解除引用指针的引用是完全合法的

答案 2 :(得分:1)

编译器不会“调用”任何东西。它只是生成代码。在最基本的级别取消引用指针将对应于某种加载指令,但在当前代码中,编译器可以轻松地优化它并直接打印该值,或者可以直接快捷地加载inum

关于你的“临时对象”:取消引用指针总是给出一个左值。

也许你的问题中隐藏着一个更有趣的问题,但是:编译器如何实现将函数参数作为引用传递?