stati c проблема порядка инициализации со статическим / динамическим c связыванием - PullRequest
2 голосов
/ 01 марта 2020

Если приложение на c ++ организовано следующим образом

//file1.cpp
static Y sgObj = X::getInitObject(0);  //declared in file scope

//file2.cpp
namespace{
   int getInitValue()
   {
      static int val = Y::sObj.initVal();
      return val;
   }
}

namespace X{
   Y getInitObject(int initVal)
   {
      if(initVal < getInitValue())
      {
         cout << "Print some log message" << endl;
      } 

      return Y::initMethod(initVal);
   }
}

//file.h
//This class is shipped as static and dynamic library, and application is supposed to link 
//them in their executable based on their need
class Y{
public:
int initVal();
static Y initMethod(int val);
static Y sObj;
};

Если все необходимые заголовочные файлы включены и мы можем создать исполняемый файл для этого приложения, возникает ли у него проблема с инициализацией, как я создаю объект в file1. cpp когда:

  • статически против
  • динамически связывается с библиотекой (соответствует реализации класса Y) для создания объекта sgObj.

Учитывая, что реализация класса Y не предоставляется приложению, мы не можем изменить способ создания его элемента c stibj.

Имеет ли он какое-либо отношение к платформе / компилятор используется?

1 Ответ

0 голосов
/ 01 марта 2020

Вы должны либо убедиться, что file1.cpp включает <iostream> до определения sgObj, либо вам необходимо создать локальный объект типа std::ios_base::Init, прежде чем использовать cout во время инициализации stati c:

  if(initVal < getInitValue())
  {
     (void)std::ios_base::Init{};
     cout << "Print some log message" << endl;
  }

В противном случае cout может не инициализироваться при достижении этой линии.


Кроме этого, порядок, в котором строятся Y::sObj и глобальный sgObj является неопределенным, при условии, что Y::sObj определено в другой не показанной единице перевода, потому что порядок, в котором происходит инициализация динамической c между различными единицами перевода, является неопределенным.

Следовательно, если Y::initMethod, который называется из глобальной инициализации sgObj доступ Y::sObj может быть еще не инициализирован, вызывая неопределенное поведение.

Если вы хотите иметь возможность использовать stati c Y::sObj во время stati c для инициализации других нелокальных переменных stati c вам нужно использовать что-то вроде одноэлементного шаблона Мейерса:

class Y{
//...
    static Y& sObj {
        static Y instance /* initializer here */;
        return instance;
    }
};

Для использования в качестве * 102 7 * вместо Y::sObj.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...