Использовать ссылку для инициализации членов класса

#c #class #reference #constants

#c #класс #ссылка #константы

Вопрос:

У меня всегда складывается впечатление, что я не должен использовать ссылку для инициализации члена класса, потому что

  1. Я не знаю время жизни ссылки и
  2. Если ссылочное значение изменяется за пределами класса, соответствующий член класса также изменится на новое значение.

Но после тестирования следующего кода я в замешательстве…

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

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

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

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

        *i = 20;
        printf("oTest.i = %dn", oTest.m_i);

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

        i = 20;
        printf("oTest.i = %dn", oTest.m_i);
    }

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

        *i = 20;
        printf("oTest.i = %dn", oTest.m_i);

        delete i;
        printf("oTest.i = %dn", 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?
  

Большое спасибо за ваш комментарий.

Ответ №1:

Ваш Test(intamp; i) :m_i(i) вызывает конструктор копирования, и поскольку ваше поле является int, а не int amp; , тесты 1 и 1.1 всегда выводят исходные 10.

В тесте 3.1 нет требования, чтобы доступ к памяти, которая была освобождена / удалена с помощью, приводил к мусору. (Существуют отладочные компиляторы, которые намеренно помещают отдельный шаблон в освобожденную память, но это часть их природы отладки.) Ничто в вашей игрушечной программе не изменяет значение, на которое указал i , так что вам это «сойдет с рук». В корпоративной программе вы получите труднодоступный «Heisenbug«.