C ++参考如何工作

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)现在我们不能使用,因为你不dump宣布,它const

1
void Dump() const

(3)在一个c = TestClass()分配。然而,现在c参考到一个常量,不能被分配到分配的,因为是非恒定的(明显的原因)。在这个黑客:Let’s

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

现在,我们已经指定新的值到该临时对象的可扩展的c和所有它应该是:

1
2
3
4
5
6
main started
data = 0  ptr = 0x0xbfa8219c
destructor
data = 10  ptr = 0x0xbfa8219c
main ended
destructor

该指针是相同的,因为只有一个目标,即通过一个相关的c(临时)。它是一assigning(这是未定义行为,在一般情况下,我们用它去,但这个演示的目的。

中间函数的第二TestClass(10)那是临时的。


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();

TestClass()创建临时,你不能把它的参考。

1
const TestClass& c = TestClass();

const合格的生活时间的延长,直到被创建的临时对象c的范围。


比较好的方法是引用的指针。(参考文献通常执行相同的方式在一般的组件利用EBX寄存器)。主要是,参考一常数差分后的初始化。

然而,const TestClass& c = TestClass();是一对平行线const TestClass* const pc = &TestClass();操作将创建该对象的破坏和在栈,PC将仍然保持相同的地址。