Можно ли заполнить массив не нулями по умолчанию?

Рейтинг: 4Ответов: 3Опубликовано: 27.12.2014

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

int ar[10] = {-1};
int ar2[10][10] = {-1,};

Можно ли как-то задать значение по умолчанию не равное нулю всем элементам массива в момент объявления? Может, что-то есть в новом стандарте? Или только циклом?

Ответы

▲ 3Принят

В Си (по крайней мере gcc (This is a GNU extension)) можно

int a[] = { [0 ... 19] = 1}

и т.п. (см. например, 5.20 Designated Initializers),
а в С++ похоже нет.

▲ 4

В C++ вы пользуетесь не нативными массивами, а STL-контейнерами.

Для них такая инициализация доступна:

vector<int> vec(5, 42);

инициализирует вектор пятью значениями 42: http://ideone.com/nOTYv9


В дополнение к отличному ответу @jfs, если скоростная инициализация важна, вы можете воспользоваться и обычным метапрограммированием:

1) пишем утилиту-генератор (generate.cpp)

#include <cstdlib>
#include <iostream>
using namespace std;

void main(int argc, int* argv[])
{
    auto val = argv[1];
    auto count = atoi(argv[2]);
    for (int i = 1; i < count; i++)
        cout << val << "," << endl;
    cout << val << endl;
}

2) Используем её в проекте:

generate 42 5 >arrinit.h

3) Ссылаемся в коде:

    int[] arr =
    {
#include "arrinit.h"
    };
▲ 3

@VladD показал две хорошие опции:

  • использовать C++ контейнеры, такие как vector, которые поддерживают подобную инициализацию
  • вызвать std::fill_n()/std::fill() -- если необходим именно обычный массив, то это предпочтительный вариант.

Пока измерения производительности не покажут, что инициализация массива является узким местом в программе, можно другие опции не рассматривать.

В качестве неразумной опции, можно произвести инициализацию массива во время компиляции с помощью шаблонов:

#include <iostream>

namespace {
  template<int... args> struct ArrayHolder {
    static const int data[sizeof...(args)];
  };

  template<int... args>
  const int ArrayHolder<args...>::data[sizeof...(args)] = { args... };

  template<size_t N, int value, int... args>
  struct generate_array {
    typedef typename generate_array<N-1, value, value, args...>::result result;
  };

  template<int value, int... args>
  struct generate_array<0, value, args...> {
    typedef ArrayHolder<args...> result;
  };
}

int main() {
  typedef generate_array<5, 42>::result A;
  for (auto x : A::data) std::cout << x << '\n';
}

Пример:

$ g++ -std=c++11 initialize-array.cc && ./a.out
42
42
42
42
42