2010-04-27 6 views
4

У меня странная проблема со статической переменной, которая, очевидно, не инициализирована, как и должно быть.
У меня есть огромный проект, который работает с Windows и Linux. Поскольку у Linux-разработчика нет этой проблемы, я бы предположил, что это какой-то проводной материал Visual Studio.

Заголовок файлаСтатическая переменная не инициализирована

class MyClass 
{ 
    // some other stuff here 
    ... 
    private: 
     static AnotherClass* const Default_; 
}; 


CPP файл

AnotherClass* const MyClass::Default_(new AnotherClass("")); 
MyClass(AnotherClass* const var) 
{ 
    assert(Default_); 
    ... 
} 

Проблема заключается в том, что Default_ всегда NULL. Я также попробовал точку останова при инициализации этой переменной, но я не могу ее поймать.

Аналогичная проблема существует в другом классе.
CPP файл

std::string const MyClass::MyString_ ("someText"); 
MyClass::MyClass() 
{ 
    assert(MyString_ != ""); 
    ... 
} 

В этом случае MyString_ всегда пусто. Так что опять не инициализировано.
У кого-нибудь есть идея? Это проблема настроек Visual Studio?
Приветствие Simon

Edit:
я наткнулся на статической инициализации краха. Но я не уверен, что это может быть проблемой, потому что нет никаких проблем с компилятором Linux. Разве компилятор не должен реагировать таким же образом в этом случае?

+0

Попробуйте создать новый проект с нуля и посмотрите, не случилось ли это там – shoosh

+0

Извините, не можете сделать. Как я уже сказал, это действительно огромный проект. –

+1

Я предполагаю, что первым примером была опечатка и должна была быть 'AnotherClass * const MyClass :: Default_ (new AnotherClass (" "));' –

ответ

6

Я предлагаю вам использовать статическую функцию-член с статической переменной и сам не статической переменной:

class MyClass 
{ 
    // some other stuff here 
    ... 
    private: 
     static AnotherClass* const getAnotherClass(); 
}; 

AnotherClass *const MyClass::getAnotherClass() 
{ 
    static AnotherClass *const p = new AnotherClass(""); 
    return(p); 
} 

стандарт гарантирует, что р инициализируется один раз, когда функция вызывается в первый раз, так что вы всегда получите правильно инициализированный объект (если вы уже не исчерпали память или бросок конструктора).

Обратите внимание: это может быть или не быть потокобезопасным (в зависимости от вашего компилятора).

И еще одно примечание - теперь вам нужно жить с «утечкой памяти», поскольку на самом деле практически невозможно решить, когда уничтожить объект, и у вас нет НИКАКОГО способа сброса p в NULL.

+0

В этом случае плохо использовать указатель. Простой экземпляр, за которым следует возврат ссылки, будет намного лучше. В конце концов, не является ли '* const' семантическим эквивалентом' & 'после удаления возможности NULL? –

+0

@Matthieu: Я просто следую приведенному коду. Для вашего комментария - вы, вероятно, правы, но на самом деле это зависит от того, что делает AnotherClass (он может, например, есть все пространство в вашем сегменте данных, поэтому для других глобал ничего не остается). – Tomek

+0

Я согласен с тем, что может быть необходимо использовать * кучу *, чтобы не насыщать сегмент данных или стек (я как бы желаю «Go» здесь ...), однако он должен быть зарезервирован, я думаю, специальным ситуации (большие объекты) и откладываются до тех пор, пока это не будет необходимо. –

0

работает на моей машине (TM):

#include <iostream> 
#include <cassert> 

class AnotherClass 
{ 
public: 
    AnotherClass(const char*) {} 
}; 

class MyClass 
{ 
public: 
    MyClass(AnotherClass* const var); 
private: 
    static AnotherClass* const Default_; 
}; 

AnotherClass* const MyClass::Default_(new AnotherClass("")); 

MyClass::MyClass(AnotherClass* const var) 
{ 
    assert(Default_); 
    std::cout << "Worked!\n"; 
} 

int main() 
{ 
    MyClass tester(NULL); 
    return 0; 
} 

Я полагаю, что проблема заключается в том, что называется конструктором другой статической переменной. Инициализация статических переменных не всегда происходит в том порядке, в котором вы хотите.

+0

Но в своем втором примере он вспомнил «MyClass ::», поэтому это, вероятно, просто опечатка в вопросе. –

+0

Да, это нужно, и это просто опечатка, но спасибо. –

+0

Ваш пример также работает для меня. –

3

В случае, если это происходит при инициализации некоторых других статических переменных, вы можете увидеть static initialization fiasco.

+0

Является ли это проблемой, связанной с компилятором Visual Studio? Или общая проблема? –

+0

@Simon: Это общая проблема. – sth

+0

Так что это не может быть моей проблемой здесь, так как у Linux-разработчика нет аналогичной проблемы ... –

2

Не должен ли компилятор реагировать таким же образом в этом случае?

№ Как я понимаю, порядок инициализации отдельных единиц компиляции НЕ УКАЗАН. Поэтому разработчику Linux повезло. Cегодня. Завтра, кто знает?

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