если у вас нет

ли я контролировать порядок уничтожения статических объектов? Есть ли способ принудительно исполнить мой желаемый приказ? Например, указать каким-либо образом, что я хотел бы, чтобы определенный объект был уничтожен последним или, по крайней мере, после другого статического объекта?

Ответы на вопрос(9)

main?

Если вы не можете использовать простую идиому, чтобы с легкостью контролировать порядок строительства и разрушения, см. Здесь:

#include <cassert>

class single {
    static single* instance;

public:
    static single& get_instance() {
        assert(instance != 0);
        return *instance;
    }

    single()
    // :  normal constructor here
    {
        assert(instance == 0);
        instance = this;
    }

    ~single() {
        // normal destructor here
        instance = 0;
    }
};
single* single::instance = 0;

int real_main(int argc, char** argv) {
    //real program here...

    //everywhere you need
    single::get_instance();
    return 0;
}

int main(int argc, char** argv) {
    single a;
    // other classes made with the same pattern
    // since they are auto variables the order of construction
    // and destruction is well defined.
    return real_main(argc, argv);
}

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

Решение Вопроса

обратном конструкции. И порядок строительства очень сложно контролировать. Единственное, в чем вы можете быть уверены, это то, что два объекта, определенных в одном и том же модуле компиляции, будут построены в порядке определения. Все остальное более или менее случайно.

 user274640115 окт. 2014 г., 15:23
Я -1, потому что этот ответ на самом деле не является ответом на вопрос ОП.
 Martin York22 янв. 2009 г., 21:33
Есть методы, чтобы обойти проблему, если вам нужен заказ: см.stackoverflow.com/questions/335369/...
 M.M16 июл. 2015 г., 02:43
Техническизавершение деструктора происходит в обратном порядкезавершение конструктора, Это имеет значение в случае, когда статический объект инициализируется во время конструктора другого. См. C ++ 14 [basic.start.term] / 1

что это не может быть сделано. И они правы, согласно спецификации - но естьявляется трюк, который позволит вам сделать это.

Создать толькоОдин статическая переменная класса или структуры, которая содержит все остальные вещи, которые вы обычно делаете статическими переменными, например:

class StaticVariables {
    public:
    StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { };
    ~StaticVariables();

    Var1Type *pvar1;
    Var2Type *pvar2;
};

static StaticVariables svars;

Вы можете создавать переменные в любом порядке, и, что более важно,уничтожить их в любом порядке, в конструкторе и деструкторе дляStaticVariables, Чтобы сделать это полностью прозрачным, вы также можете создавать статические ссылки на переменные, например:

static Var1Type &var1(*svars.var1);

Вуаля - тотальный контроль. :-) Тем не менее, это дополнительная работа, и, как правило, не нужно. Но когда этоявляется необходимо, это очень полезно знать об этом.

static std::optional<T> вместоT, Просто инициализируйте его так же, как и в случае с переменной, используйте с косвенным путем и уничтожьте его, назначивstd::nullopt (или, для повышения,boost::none).

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

использованиеboost::optional<T> если у вас нетstd:: / std::experimental::.

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

В Visual C ++ указатели на статические функции инициализации находятся в.CRT$XI сегмент (для статического init типа C) или.CRT$XC сегмент (для статической инициализации типа C ++) Компоновщик собирает все объявления и объединяет их в алфавитном порядке. Вы можете контролировать порядок статической инициализации, объявляя ваши объекты в соответствующем сегменте, используя

#pragma init_seg

например, если вы хотите, чтобы объекты файла A создавались до файла B:

Файл A.cpp:

#pragma init_seg(".CRT$XCB")
class A{}A;

Файл B.cpp:

#pragma init_seg(".CRT$XCC")
class B{}B;

.CRT$XCB сливается в ранее.CRT$XCC, Когда CRT перебирает статические указатели на функцию инициализации, он сталкивается с файлом A перед файлом B.

В Watcom сегмент XI, и варианты инициализации #pragma могут управлять конструкцией:

#pragma initialize before library
#pragma initialize after library
#pragma initialize before user

... см. документацию для более

обратном порядку их создания (например, первый созданный объект уничтожается последним), и вы можете контролировать последовательность, в которой создаются статические объекты, используя технику, описанную в пункте 47, "Убедитесь, что глобальные объекты инициализируются перед использованием"в книге МейерсаЭффективный C ++.

Например, указать каким-либо образом, что я хотел бы, чтобы определенный объект был уничтожен последним или, по крайней мере, после другого статического объекта?

Убедитесь, что он построен перед другим статическим объектом.

Как я могу контролировать строительный заказ? не все статики находятся в одной и той же dll.

Я буду игнорировать (для простоты) тот факт, что они не находятся в одной и той же DLL.

Мой перефразирование пункта 47 Мейерса (длина которого составляет 4 страницы) выглядит следующим образом. Предполагая, что вы глобально определены в заголовочном файле, как это ...

//GlobalA.h
extern GlobalA globalA; //declare a global

... добавить код в этот файл включения, как это ...

//GlobalA.h
extern GlobalA globalA; //declare a global
class InitA
{
  static int refCount;
public:
  InitA();
  ~InitA();
};
static InitA initA;

Результатом этого будет то, что любой файл, который включает в себя GlobalA.h (например, ваш исходный файл GlobalB.cpp, который определяет вашу вторую глобальную переменную), будет определять статический экземпляр класса InitA, который будет построен прежде всего в этом исходный файл (например, перед вашей второй глобальной переменной).

Этот класс InitA имеет статический счетчик ссылок. Когда создается первый экземпляр InitA, который теперь гарантированно будет создан до создания вашего экземпляра GlobalB, конструктор InitA может делать все, что должен, для обеспечения инициализации экземпляра globalA.

 ChrisW22 янв. 2009 г., 17:21
Отредактировано, чтобы ответить на ваш вопрос
 Gal Goldman22 янв. 2009 г., 16:59
Как я могу контролировать строительный заказ? не все статики находятся в одной и той же dll.

ты не можешь. Вы никогда не должны полагаться на другое строительство / разрушение статических объектов.

Вы всегда можете использовать синглтон для управления порядком строительства / уничтожения ваших глобальных ресурсов.

Немного более длинный ответ: Для глобальных статических объектов в одной единице перевода порядок инициализации сверху вниз, порядок уничтожения в точности обратный. Порядок между несколькими единицами перевода не определен.

Если вам действительно нужен конкретный заказ, вы должны сделать это самостоятельно.

 gimpf22 янв. 2009 г., 17:10
Извините, я не смог понять этот комментарий. Да, порядок между единицами перевода является случайным. Я сказал что-то еще?
 Robert Gould23 янв. 2009 г., 02:57
Чувак! Был ли я когда-нибудь сонным, когда писал это! Даже понятия не имею, что я имел ввиду :)
 Robert Gould22 янв. 2009 г., 16:39
Хотя ваш заказ я обычно прав, я думаю, что стандарт не требует порядка, поэтому он действительно зависит от компилятора.

Ваш ответ на вопрос