Когда статические участники класса C++ инициализируются?

Я просто реализовал быстрое тестовое приложение и представил его с МУРАВЬЯМИ 4.
Спецификация:.Net 3.5 sp1 в Windows XP на 32 бита, код создается в режиме выпуска.

3 миллиона тестов:

  • Переключатель: 1,842 секунды
  • , Если: 0,344 секунды.

, Кроме того, результаты оператора переключения показывают (неудивительно), что более длинные имена занимают больше времени.

1 миллион тестов

  • Bob: 0,612 секунды.
  • Jill: 0,835 секунды.
  • Marko: 1,093 секунды.

я похож, "Если Еще" быстрее, по крайней мере, сценарий, я создал.

class Program
{
    static void Main( string[] args )
    {
        Bob bob = new Bob();
        Jill jill = new Jill();
        Marko marko = new Marko();

        for( int i = 0; i < 1000000; i++ )
        {
            Test( bob );
            Test( jill );
            Test( marko );
        }
    }

    public static void Test( ChildNode childNode )
    {   
        TestSwitch( childNode );
        TestIfElse( childNode );
    }

    private static void TestIfElse( ChildNode childNode )
    {
        if( childNode is Bob ){}
        else if( childNode is Jill ){}
        else if( childNode is Marko ){}
    }

    private static void TestSwitch( ChildNode childNode )
    {
        switch( childNode.Name )
        {
            case "Bob":
                break;
            case "Jill":
                break;
            case "Marko":
                break;
        }
    }
}

class ChildNode { public string Name { get; set; } }

class Bob : ChildNode { public Bob(){ this.Name = "Bob"; }}

class Jill : ChildNode{public Jill(){this.Name = "Jill";}}

class Marko : ChildNode{public Marko(){this.Name = "Marko";}}
60
задан Tony the Pony 14 September 2009 в 14:02
поделиться

6 ответов

Стандарт гарантирует две вещи: объекты, определенные в одной единице трансляции (обычно это означает файл .cpp), инициализируются в порядке их определения ( не объявления ):

3.6.2

Хранилище для объектов со статической продолжительностью хранения (basic.stc.static) должно быть инициализировано нулем (dcl.init) перед любым другим инициализация происходит. Нулевая инициализация и инициализация с постоянным выражением все вместе называются статической инициализацией; вся остальная инициализация - это динамическая инициализация. Объекты типов POD (basic.types) со статической продолжительностью хранения, инициализированные константными выражениями (expr.const), должны быть инициализированы до того, как произойдет какая-либо динамическая инициализация. Объекты со статической продолжительностью хранения, определенной в области пространства имен в той же единице трансляции и динамически инициализированной, должны быть инициализированы в том порядке, в котором их определение появляется в единице трансляции.

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

Это определяется реализацией, будет ли динамическая инициализация (dcl.init, class.static, class.ctor, class.expl.init) объекта объект области пространства имен выполняется перед первым оператором main. Как указано в комментарии Suma, также гарантируется, что они инициализируются до ввода main .

55
ответ дан 24 November 2019 в 17:52
поделиться

Я думаю, что основной поток процесса будет выполнять следующие пять шагов в порядке

  1. инициализации библиотеки CRT

  2. статической инициализации

  3. выполнения функции main ()

  4. статическая унитиализация

  5. унитализация библиотеки CRT

вы хотите ссылочную статику из другого статического кода инициализации? возможно, работают следующие коды:

class A;
static auto_ptr<A> a(auto_ptr<A>(&GetStaticA()));
A &GetStaticA(void)
{
    static A *a = NULL; //the static basic type variables initialized with constant experession will be initialized earlier than the other static ones
    if (a == NULL)
    {
         a = new A();
         return *a;
    }
}
-1
ответ дан 24 November 2019 в 17:52
поделиться

Они инициализируются перед запуском программы (т.е. перед вводом main ).

Когда в одном файле CPP есть два или более определений (статических данных), они инициализируются в той последовательности, в которой они определены в файле (определенное ранее / выше в файле инициализируется до того, как будет выполнено следующее).

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

19
ответ дан 24 November 2019 в 17:52
поделиться

Их можно инициализировать в файлах файла реализации (.c / cpp / cc). Не инициализируйте их в .h, так как компилятор будет жаловаться на несколько определений.

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

1
ответ дан 24 November 2019 в 17:52
поделиться

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

1
ответ дан 24 November 2019 в 17:52
поделиться

На этот вопрос нет однозначного ответа, но в основном они инициализируются непосредственно перед передачей управления в точку входа (основную) вашей программы. Порядок, в котором они инициализируются, (насколько мне известно) не определен и может зависеть от компилятора

РЕДАКТИРОВАТЬ: Чтобы уточнить, ваше добавленное предположение является правильным. Пока вы обращаетесь к нему только после основной записи, вам действительно не нужно беспокоиться о том, когда и как он инициализируется. К этому времени он будет инициализирован.

0
ответ дан 24 November 2019 в 17:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: