C ++参考如何工作

时间:2011-09-14 14:58:49

标签: c++ reference

在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;
}

5 个答案:

答案 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仍将保持相同的地址。