Статическая переменная внутри конструктора, есть ли недостатки или побочные эффекты? - PullRequest
3 голосов
/ 30 мая 2010

Что я хочу сделать: запускать некоторый обязательный код всякий раз, когда экземпляр класса будет использоваться внутри программы. Этот код проверяет наличие требований и т. Д., И его следует запускать только один раз.

Я обнаружил, что этого можно достичь, используя другой объект в качестве статической переменной внутри конструктора. Вот пример для лучшей картинки:

class Prerequisites
{
     public:
         Prerequisites() {
              std::cout << "checking requirements of C, ";
              std::cout << "registering C in dictionary, etc." << std::endl;
         }
};


class C
{
    public:
         C() {
             static Prerequisites prerequisites;
             std::cout << "normal initialization of C object" << std::endl;
         }
};

Что меня беспокоит, так это то, что я до сих пор не видел подобного использования статических переменных. Есть ли недостатки или побочные эффекты, или я что-то упустил? Или, может быть, есть лучшее решение? Любые предложения приветствуются.

Ответы [ 3 ]

5 голосов
/ 30 мая 2010

Это не потокобезопасно, поскольку, если два потока попытаются создать C в первый раз в одно и то же время, предварительные условия, вероятно, будут инициализированы дважды.

Если вы согласны с этим, вы, вероятно, можете сделать это, хотя игра в системе конструкторов с заданной областью имеет нулевое обнаружение (т. Е. Как только вы забудете «трюк» или другие попытаются прочитать ваш код, они будут озадачены что происходит).

4 голосов
/ 30 мая 2010

Есть ли какие-либо недостатки или побочные эффекты, или я что-то упустил? Или, может быть, есть лучшее решение? Любые предложения приветствуются.

Возможно, было бы яснее (хотя и более многословно) явно вызывать статический метод.

class Prerequisites
{
    static bool checkedOnce;    
public:
    static void checkOnce() {
        if (checkedOnce)
        {
            //already checked: don't check again
            return;
        }
        //else check them now
        checkedOnce = true;
        std::cout << "checking requirements of C, ";
        std::cout << "registering C in dictionary, etc." << std::endl;
    }
};

bool Prerequisites::checkedOnce = false;

class C
{
public:
    C() {
        Prerequisites::checkOnce();
        std::cout << "normal initialization of C object" << std::endl;
    }
};
1 голос
/ 30 мая 2010

Вы должны по крайней мере использовать мьютекс и статический флаг внутри класса Prerequisites для защиты от множественной инициализации объектов Prerequisites. Таким образом, ваш код станет потокобезопасным.

...