C++ 参考的工作原理

Posted

技术标签:

【中文标题】C++ 参考的工作原理【英文标题】:How C++ reference works 【发布时间】:2011-11-17 02:57:51 【问题描述】:

在 C++ 工作了 15 年之后,我发现我并不完全理解引用...

类测试类 民众: 测试类():m_nData(0) 测试类(int n):m_nData(n) ~TestClass() cout

我从这个测试中了解到,TestClass 实例是在堆栈上创建的(这是正确的吗?)并由第一个 TestClass 构造函数初始化。什么时候分配这个实例:什么时候加载主函数,或者执行引用赋值?什么时候销毁?

第二次引用赋值后对象地址不变。这是否意味着析构函数和构造函数应用于同一个内存区域?或者内存被释放(动态?在堆栈上?)并再次分配?

我对堆栈和堆分配对象的生命周期、它们的构造函数和析构函数了如指掌。但我无法理解这个程序到底发生了什么。

编辑: 谢谢大家。我试图在这个测试中重现一些其他(更复杂的)程序行为。您的 cmets 帮助我理解了我的错误和我正在与之抗争的另一个程序......

固定代码为:

主函数() cout

【问题讨论】:

此代码无法编译。您不能将非常量引用绑定到临时对象。 是否有任何不将自动对象放入堆栈的 C++ 实现?如果有,它们是哪些? 你用哪个编译器来编译它?它不应该编译。 @Jeremy:没有,这在逻辑上是不可能的。令人费解的是,那些宣传城市神话的人都是白痴。我无法解释他们为什么这样做,除了可能就像那个因与人行道发生性关系而被判刑的苏格兰人一样,这只是莫名其妙的行为。 请保持 cmets 具有建设性和主题性。 【参考方案1】:

您的代码存在多个问题,最终没有意义。但是,让我们破解它。

1) 您只能将临时对象绑定到 const 引用,从而延长其生命周期:

const TestClass & c = TestClass();

2) 现在我们不能使用dump,因为你没有声明它const

void Dump() const

3) 说c = TestClass() 是一项任务。然而,c 现在是一个对 const 的引用,它不能被赋值,因为赋值是非常量的(原因很明显)。让我们解决这个问题:

const_cast<TestClass&>(c) = TestClass(10);

现在我们为临时但扩展的对象c 分配了一个新值,一切正常:

main started
data = 0  ptr = 0x0xbfa8219c
destructor
data = 10  ptr = 0x0xbfa8219c
main ended
destructor

指针是相同的,因为只有一个对象,即c 引用的(临时)对象。分配给它是一种黑客行为,通常是未定义的行为,但出于本演示的目的,我们侥幸逃脱。

中间析构函数是第二个临时TestClass(10)的析构函数。

【讨论】:

【参考方案2】:
TestClass& c = TestClass(); // TestClass() temporary doesn't persist beyond this expression.
c.Dump();

TestClass() 会创建一个临时对象,您不能对其进行引用。

const TestClass& c = TestClass();

const 限定将被创建的临时对象的生命周期延长到对象c 的范围。

【讨论】:

【参考方案3】:
TestClass& c = TestClass();

这甚至无法编译!

尝试将临时引用绑定到非常量引用会导致编译错误。

但是,您可以将临时绑定到 const 引用:


   const TestClass& c = TestClass();
   //use c 
   //....
//<-------- the temporary will be destroyed here.

在这种情况下,临时变量的生命周期延长到引用的生命周期,即当引用变量超出范围时,临时变量将被销毁,如上所示。

【讨论】:

这在 VC++ 2010 中编译,带有警告 C4239(级别 4)。 @Alex:warning 明确表示:使用了非标准扩展:“token”:从“type”转换为“type”。 ....你看到粗体字了吗? 一些警告应该被视为错误...... MCVC 非常宽容。【参考方案4】:

1) 你不能得到对临时对象的非 const 引用

2) 在行 c = TestClass(10); operator=(...) 被调用

【讨论】:

【参考方案5】:

一个好方法是比较指针的引用...(引用通常在汇编中以相同的方式实现,通常使用 ebx 寄存器)。主要区别在于初始化后引用是常量...

但是,const TestClass&amp; c = TestClass(); 行与const TestClass* const pc = &amp;TestClass(); 平行,因此对象将在堆栈​​上创建和销毁,pc 仍将保持相同的地址。

【讨论】:

以上是关于C++ 参考的工作原理的主要内容,如果未能解决你的问题,请参考以下文章

C++ 放置新的工作原理是啥?

memset() 在 C++ 中的工作原理

C++中虚函数工作原理和(虚)继承类…

C++中的奇淫技巧,三种函数调用方法,让小白彻底理解其工作原理

基于arm的C++反汇编 函数的工作原理

javascript引擎工作原理