使用引用初始化类成员

问题描述

我总是觉得我不应该使用引用来初始化类成员,因为

  1. 我不知道参考文献的有效期,
  2. 如果参考值在类外更改,则相应的类成员也将更改为新值。

但是在测试了以下代码之后,我很困惑...

class Test
{
public: 
    Test(int& i) :m_i(i) {}
    int m_i;
};

class Test3
{
public:
    Test3(int& i) :m_i(i) {}
    const int& m_i;
};

int main()
{
    {
        std::cout << "\n// Test 1" << std::endl;
        int i = 10;
        Test oTest(i);
        printf("oTest.i = %d\n",oTest.m_i);

        i = 20;
        printf("oTest.i = %d\n",oTest.m_i);
    }
    {
        std::cout << "\n// Test 1.1" << std::endl;
        int* i = new int;
        *i = 10;
        Test oTest(*i);
        printf("oTest.i = %d\n",oTest.m_i);

        *i = 20;
        printf("oTest.i = %d\n",oTest.m_i);

        delete i;
        printf("oTest.i = %d\n",oTest.m_i);
    }
    {
        std::cout << "\n// Test 3" << std::endl;
        int i = 10;
        Test3 oTest(i);
        printf("oTest.i = %d\n",oTest.m_i);
    }

    {
        std::cout << "\n// Test 3.1" << std::endl;
        int* i = new int;
        *i = 10;
        Test3 oTest(*i);
        printf("oTest.i = %d\n",oTest.m_i);
    }

    return 0;
}

输出如下:

// Test 1
oTest.i = 10
oTest.i = 10          <---- Why not 20?

// Test 1.1
oTest.i = 10
oTest.i = 10          <---- Why not 20?
oTest.i = 10          <---- Why not some garbage number?

// Test 3
oTest.i = 10
oTest.i = 20

// Test 3.1
oTest.i = 10
oTest.i = 20
oTest.i = 20          <---- Why not some garbage number?

非常感谢您的评论

解决方法

您的Test(int& i) :m_i(i)调用 copy 构造函数,并且由于您的字段是int而不是int&,因此test 1和1.1始终显示原始10。

在测试3.1中,没有要求要求访问已被释放/删除的内存会产生垃圾。 (有一些调试编译器会在释放的内存中故意放入一个独特的模式,但这是其调试性质的一部分。)您的Toy程序中的任何内容都不会更改{{1}所指向的值},这样您就可以“摆脱它”。在企业程序中,您将得到一个很难找到的“ Heisenbug”。