How C++ reference works
在C++工作了15年之后,我发现我完全不了解参考文献。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | class TestClass { public: TestClass() : m_nData(0) { } TestClass(int n) : m_nData(n) { } ~TestClass() { cout <<"destructor" << endl; } void Dump() { cout <<"data =" << m_nData <<" ptr = 0x" << hex << this << dec << endl; } private: int m_nData; }; int main() { cout <<"main started" << endl; TestClass& c = TestClass(); c.Dump(); c = TestClass(10); c.Dump(); cout <<"main ended" << endl; return 0; } // prints: // main started // data = 0 ptr = 0x0012FF54 // destructor // data = 10 ptr = 0x0012FF54 // main ended // destructor |
我从这个测试中了解到,testclass实例是在堆栈上创建的(这是正确的吗?)并由第一个testclass构造函数初始化。当分配这个实例时:加载主函数或执行引用分配时?当它被摧毁?
第二次引用分配后,对象地址不变。这是否意味着析构函数和构造函数被应用到同一个内存区域?或者内存被释放(动态地?在堆栈上?)又分配了吗?
我知道关于栈和堆分配对象生存期的所有信息,它们的构造函数和析构函数。但我不能理解这个程序到底发生了什么。
编辑:谢谢大家。我试图在这个测试中重现一些其他(更复杂的)程序行为。你的评论帮助我理解了我的错误和我正在与之斗争的另一个计划…
固定码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int main() { cout <<"main started" << endl; TestClass t; TestClass& c(t); c.Dump(); c = TestClass(10); c.Dump(); cout <<"main ended" << endl; return 0; } |
你的问题与患者或从多个代码最终会使意识。然而,Let’s黑客通过它。
1)你只能暂时绑定到const引用,从而延长其寿命。
1 | const TestClass & c = TestClass(); |
2)现在我们不能使用,因为你不
1 | void Dump() const |
(3)在一个
1 | const_cast<TestClass&>(c) = TestClass(10); |
现在,我们已经指定新的值到该临时对象的可扩展的
1 2 3 4 5 6 | main started data = 0 ptr = 0x0xbfa8219c destructor data = 10 ptr = 0x0xbfa8219c main ended destructor |
该指针是相同的,因为只有一个目标,即通过一个相关的
中间函数的第二
1)你不能让非const引用临时对象。
2)在网络(10);c=TestClass)一个被称为算子(?)
1 | TestClass& c = TestClass(); |
这不是甚至重新编译!
对临时attempting绑定到非const引用将导致编译错误。
然而,你可以暂时绑定到const引用。
1 2 3 4 5 | { const TestClass& c = TestClass(); //use c //.... }//<-------- the temporary will be destroyed here. |
在这个案例的生命的延伸,在临时的寿命的参考,即当参考变量超出范围的推移,临时将显示在M。
1 2 | TestClass& c = TestClass(); // TestClass() temporary doesn't persist beyond this expression. c.Dump(); |
1 | const TestClass& c = TestClass(); |
比较好的方法是引用的指针。(参考文献通常执行相同的方式在一般的组件利用EBX寄存器)。主要是,参考一常数差分后的初始化。
然而,