2016-05-05 2 views
0

Я пытаюсь использовать следующий код C++, который инициализирует переменные-члены c1 и c2 на основе статических переменных v1 и v2 в разных пространствах имен. Мне кажется, что циклическая зависимость возникает для инициализации этих переменных.Циклическая зависимость инициализации члена

#include <iostream> 

namespace M1 
{ 
    struct T1 
    { 
     int c1; 
     T1(); 
    }; 

    T1 v1; 
} 

namespace M2 
{ 
    struct T2 
    { 
     int c2; 
     T2() { c2 = M1::v1.c1; }   // (1) 
     // T2() : c2(M1::v1.c1) {}  // (2) 
    }; 

    T2 v2; 
} 

M1::T1::T1() { c1 = M2::v2.c2; }   // (3) 
// M1::T1::T1() : c1(M2::v2.c2) {}  // (4) 


int main() 
{ 
    std::cout << M1::v1.c1 << std::endl; 
    std::cout << M2::v2.c2 << std::endl; 

    return 0; 
} 

Однако, если я скомпилировать этот код с г ++ - 5,3 (установлен с помощью доморощенного на OSX 10.9), оно всегда успешно выполняет (без предупреждения с -Wall) и дает

0 
0 

Я также попытался заменяя линии (1) и (3) на (2) и (4), но никаких изменений в результатах (т. е. 0 и 0). Поэтому мне интересно, почему этот код работает успешно. Здесь нет циклической зависимости? Если нет, то результат просто неопределен? (т. е. данные мусора в памяти для c1 и c2 напечатаны?) Я был бы признателен за любые намеки на это поведение. Благодаря!

ответ

2

Да, у вас есть круговая зависимость, поскольку значения инициализируются друг от друга.

Там нет ошибки почти по той же причине, что вы не получите сообщение об ошибке в следующем:

int x; 
std::cout << x; 

в том, что, логически, вы просто используете неинициализированные переменные. Значение будет неуказано, и компилятор не сможет обнаружить это в общем случае, так что это ни в коем случае.

Однако мы также должны помнить, что объекты статической продолжительности хранения инициализируются нулем, прежде чем произойдет что-либо еще, поэтому ваша программа на самом деле четко определена.

Это означает, что M2::v2.c2, безусловно, будет инициализирован нулем; как следствие, M1::v1.c1 также будет инициализирован до нуля.

+0

Хм, я все еще очень смущен ... Эта страница SO http://stackoverflow.com/questions/7207884/class-construction-with-initial-values, похоже, объясняет, что примитивные типы типа 'int' не имеют предварительно определенные значения для инициализации ... Это неправильно, а на самом деле всегда нулевое инициализировано? (если другое назначение не происходит?) (см. Приложение «1» в ответе.) – septc

+0

@spectrum: страница верна, но она говорит о переменных-членах класса. Вы используете глобальные переменные. Две вещи не то же самое. –

+0

@spectrum Ссылка на объекты с * автоматическим временем хранения *, которые по умолчанию не инициализированы для примитивных типов. Инициализация нуля выполняется для * статической продолжительности хранения *, например, в вашем случае глобальных переменных. – lisyarus

Смежные вопросы