Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Инициализировать переменные массива одним значением без цикла?

#cpp #массивы


1) Скажите, пожалуйста, возможно ли на С++ как нибудь инициализировать все значения
массива одним и тем же значением, не используя цикл?
Или можно ли как-то по-другому решить следующую проблему...
У меня в классе есть массив

static bool result[M];


Я хочу, чтобы первоначально все значения данного массива были true . В процессе,
мне потребуется их менять. 
Была идея сделать цикл 

for (i = 0; i < M; i++) result[i] = true; 

в конструкторе класса, но тогда ведь он будет выполняться при каждом создании объекта...
Значит так делать не стоит..? 
Подскажите пожалуйста, что сделать)

--

2) И вопрос 2(еще более дурацкий).
Допустим, у меня есть глобальная переменная const int N = 5.
Мне нужно создать глобальную переменную const int M, которая будет равно 10 в степени
N. Функцией pow в таком случае пользоваться нельзя, как тогда можно это сделать? 
    


Ответы

Ответ 1



1) Вы не можете избежать инициализации. Но вы можете объявить статическим не массив, а целый объект класса с конструктором: template struct InitializedArray { bool data[M]; InitializedArray() { for (int i = 0; i < M; i++) data[i] = true; } } ... static InitializedArray result; 2) Вам подойдёт вот такой трюк с шаблоном: const int N = 5; template struct power_of_10 { static const int value = 10 * power_of_10::value; }; template<> struct power_of_10<0> { static const int value = 1; }; const int M = power_of_10::value;

Ответ 2



Не зная M, массив можно проинициализировать только дефолтными значениями типа, т.е. false. В случае статического или глобального массива это происходит автоматически, в случае не статического можно возпользоваться одним из эквивалентных способов: bool arr[10] = {0}; // Работает даже в С bool arr[10] = {false}; bool arr[10] = {}; Проставлять значения при каждом вызове конструктора конечно не стоит. Я вижу несколько вариантов решения вашей проблемы. Простое решение. Можно поменять смысл, который несут значения вашего массива на противоположный. Например, если это был массив isResourceAvailable, переименовать его в isResourceBusy. Тогда дефолтная инициализация будет правильной. Универсальное решение. Создать метод (возможно статический) для инициализации статических переменных, и убедиться, что этот метод будет иметь эффект только при первом вызове. А потом вызывать его при конструировании каждого объекта. Выглядеть это будет как-то так: class MyClass { public: MyClass() { MaybeInitializeStatic(); } private: static void MaybeInitializeStatic() { static bool initialized; if (initialized) return; initialized = true; std::fill_n(arr, M, true); } static bool arr[M]; }; Стоит отметить, что такое решение подходит только для однопоточной программы. Чтобы сделать его thread-safe, нужно добавить синхронизацию: static void MaybeInitializeStatic() { static bool initialized; static std::mutex mutex; if (initialized) { return; } else { std::unique_lock lock(mutex); if (initialized) return; std::fill_n(arr, M, true); initialized = true; } } Еще одно универсальное решение, даже лучше предыдущего. Вызывать функцию во время инициализации другой статической переменной. class MyClass { public: MyClass() {} private: static void InitializeStatic() { std::fill_n(arr, M, true); } static bool arr[M]; static int unused; }; int MyClass::unused = (InitializeStatic(), 0xDeadBeef); Тут не нужна ни синхронизация, ни проверка того, что функция будет вызвана только один раз.

Ответ 3



1) Если Вы боретесь за скорость, замените цикл на memset(result, 0xFF, sizeof(result)) В любом случае кто-то должен выставить единички в памяти, из ниоткуда они там не возьмутся. Так пусть хотя бы это будет делаь функция, задача которой - делать это и делать максимально эффективно.

Ответ 4



Вы можете использовать std::vector вместо массива, у него есть конструктор, который заполняет его нужным значением: std::vector result(M, true);

Комментариев нет:

Отправить комментарий