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& c = TestClass();
行与const TestClass* const pc = &TestClass();
平行,因此对象将在堆栈上创建和销毁,pc 仍将保持相同的地址。
【讨论】:
以上是关于C++ 参考的工作原理的主要内容,如果未能解决你的问题,请参考以下文章