Заполнение глобального статического массива при запуске - PullRequest
2 голосов
/ 23 июня 2019

Как я могу заполнить статический массив при запуске, кроме указания исчерпывающего списка его элементов в источнике (раздутый источник и двоичный файл)?

Это лучшее, что я мог придумать длядинамически заполнить array значениями от 0 до 99:

int array[100];

struct FillArray {
    FillArray() {
        std::iota(std::begin(array), std::end(array), 0);
    }
};

FillArray dummy;

Существует ли более идиоматический шаблон для этого?

Определение массива не может измениться: оно должнодля вызова кода выглядят как статический массив (например, не предлагайте использовать std::array).


Обратите внимание, что я не пытаюсь решить проблему порядка статической инициализации.То есть вы можете предположить, что, кроме инициализации, к массиву снова не будет доступа, пока не начнется main().

1 Ответ

1 голос
/ 23 июня 2019

Вам нужна некая версия Счетчика Шварца (более известного как Счетчик Nifty).

Счетчик Nifty используется для инициализации нелокального статического объектаперед первым использованием в вашей программе и уничтожить его после последнего использования.

Пример счетчика Nifty в библиотеке std: std :: cout.

Вот пример дляваш вариант использования:

// GlobalArray.hpp

#pragma once

#include <array>

struct GlobalArray // This the the struct containing the 'static' object we want 
{
    GlobalArray();
    ~GlobalArray();
    std::array<int, 100> array;

};
extern GlobalArray& global_array; // This is the variable containing the reference to the constructed 'static' object. 

static struct GlobalArrayInit
{
    GlobalArrayInit();
    ~GlobalArrayInit();
} global_array_init;

А теперь ...

// GlobalArray.cpp

#include "GlobalArray.hpp"

static int nifty_counter; // zero initialised at load time
static typename std::aligned_storage<sizeof (GlobalArray), alignof (GlobalArray)>::type
  global_array_buf; // memory for the global_array object
GlobalArray& global_array = reinterpret_cast<GlobalArray&> (global_array_buffer);

GlobalArray::GlobalArray ()
{
  // initialize things
}
GlobalArray::~GlobalArray ()
{
  // clean-up
} 

GlobalArrayInit::GlobalArrayInit ()
{
  if (nifty_counter++ == 0) new (&global_array) GlobalArray (); // placement new
}
GlobalArrayInit::~GlobalArrayInit ()
{
  if (--nifty_counter == 0) (&global_array)->~GlobalArray ();
}

Обратите внимание, что вы ДОЛЖНЫ включить заголовок перед использованием объекта 'global_array', чтобы убедиться, что он созданправильно.

Если вы хотите подробнее узнать о том, как это работает, и откуда у меня появилась идея исходного кода, прочитайте это: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter

...