使用引用初始化class个成员

Use reference to initialize class members

我一直觉得我不应该使用引用来初始化 class 成员,因为

  1. 我不知道引用的生命周期和
  2. 如果参考值在 class 之外发生变化,相应的 class 成员也会更改为新值。

但是测试了下面的代码后,我很困惑...

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

        i = 20;
        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);

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

        delete 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&,测试 1 和 1.1 总是打印原始的 10。

在测试 3.1 中,没有要求 访问已经freed/deleted 的内存会产生垃圾。 (有些调试编译器故意 在释放的内存中放置 一个不同的模式,但这是它们调试性质的一部分。)你的玩具程序中没有任何东西改变 [=指向的值=11=],所以你“侥幸逃脱”。在企业程序中,你会得到一个hard-to-find "Heisenbug".