在C ++工作了15年后,我发现我完全不理解参考文献......
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构造函数初始化。分配此实例时:加载主函数或执行引用赋值时?当它被摧毁?
第二次引用后,分配对象地址未更改。这是否意味着析构函数和构造函数应用于同一个内存区域?或者内存被解除分配(在堆栈上动态?)并再次分配?
我知道堆栈和堆分配对象的生命周期,它们的构造函数和析构函数。但是我无法理解这个程序到底发生了什么。
修改 谢谢大家。我试图在这个测试中重现一些其他(更复杂的)程序行为。你的评论帮助我理解了我的错误以及我正在与之抗争的其他计划......
固定代码是:
int main() { cout << "main started" << endl; TestClass t; TestClass& c(t); c.Dump(); c = TestClass(10); c.Dump(); cout << "main ended" << endl; return 0; }
答案 0 :(得分:5)
您的代码遇到了多个问题,最终没有意义。但是,让我们破解它。
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)
。
答案 1 :(得分:2)
TestClass& c = TestClass(); // TestClass() temporary doesn't persist beyond this expression.
c.Dump();
TestClass()
创建一个临时的,你不能参考它。
const TestClass& c = TestClass();
const
限定条件将临时创建的生命周期延长到对象c
的范围。
答案 2 :(得分:2)
TestClass& c = TestClass();
这甚至不会编译!
尝试将临时引用绑定到非const引用会导致编译错误。
但是,您可以将临时绑定到const引用:
{
const TestClass& c = TestClass();
//use c
//....
}//<-------- the temporary will be destroyed here.
在这种情况下,临时的寿命延长到引用的生命周期,即当引用变量超出范围时,临时将被销毁,如上所示。
答案 3 :(得分:2)
1)你不能得到const引用临时对象
2)在行c = TestClass(10); operator =(...)被称为
答案 4 :(得分:1)
一种好方法是比较对指针的引用...(引用通常通过使用ebx寄存器在程序集中以相同的方式实现)。主要区别在于初始化后引用是不变的......
然而,行const TestClass& c = TestClass();
与const TestClass* const pc = &TestClass();
并行,因此对象将在堆栈上创建和销毁,pc仍将保持相同的地址。