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

MWr*_*ght 41 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;          

}
Run Code Online (Sandbox Code Playgroud)

是否有临时对象产生?

Mik*_*our 39

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

如果它按值获取参数,则会创建一个本地副本,并返回对该参数的引用将是错误的,如果访问它则给出未定义的行为.


Wug*_*Wug 27

书面答案你的问题

不,这个行为是定义的.除非程序员明确指定,否则在指针类型被解除引用或使用引用类型时不会调用构造函数,就像下面的代码片段一样,其中new运算符调用该int类型的默认构造函数.

int* variable = new int;
Run Code Online (Sandbox Code Playgroud)

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

returnSame(*pinum) = 10;
std::cout << "inum: " << inum << std::endl;
Run Code Online (Sandbox Code Playgroud)

更深入的分析

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

int& returnSame( int &example ) { return example; } // semi instead of colon
Run Code Online (Sandbox Code Playgroud)

指针和参考

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

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

片段分析

int *pinum = & inum;
Run Code Online (Sandbox Code Playgroud)

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

*pinum
Run Code Online (Sandbox Code Playgroud)

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

returnSame(*pinum)
Run Code Online (Sandbox Code Playgroud)

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

int* returnSamePointer( int *example ) { return example; }
Run Code Online (Sandbox Code Playgroud)

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

std::cout << "inum: " <<  *(returnSamePointer(pinum)) << std::endl;
Run Code Online (Sandbox Code Playgroud)

NULL引用

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

int& nullRef = *((int *) NULL);      // creates a reference to nothing
bool isRefNull = (&nullRef == NULL); // true
Run Code Online (Sandbox Code Playgroud)

摘要

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

  • 巨大的文本块耶。我可能会对错别字进行大约 8 次编辑 (2认同)