Как инициализировать все элементы в массиве к одному и тому же номеру в C ++ - PullRequest
17 голосов
/ 23 мая 2010

Я пытаюсь инициализировать массив int со всем, установленным в -1.

Я попробовал следующее, но это не работает. Он устанавливает только первое значение -1. ​​

int directory[100] = {-1};

Почему это не работает правильно?

Ответы [ 14 ]

34 голосов
/ 23 мая 2010

Я удивлен всеми ответами, предлагающими vector. Они даже не одно и то же!

Использование std::fill, от <algorithm>:

int directory[100];
std::fill(directory, directory + 100, -1);

Непосредственно не связан с вопросом, но вам может понадобиться хорошая вспомогательная функция, когда речь идет о массивах:

template <typename T, size_t N>
T* end(T (&pX)[N])
{
    return pX + N;
}

Предоставление:

int directory[100];
std::fill(directory, end(directory), -1);

Так что вам не нужно указывать размер дважды.

7 голосов
/ 23 мая 2010

Я бы предложил использовать std::array.По трем причинам:
1. массив обеспечивает защиту во время выполнения от индекса вне пределов в операциях подписки (т. Е. operator[]),
2. массив автоматически переносит размер без необходимости передавать его отдельно
3. И самое важное, массив предоставляет метод fill(), необходимый для этой проблемы

#include <array>
#include <assert.h>

typedef std::array< int, 100 > DirectoryArray;

void test_fill( DirectoryArray const & x, int expected_value ) {
    for( size_t i = 0; i < x.size(); ++i ) {
        assert( x[ i ] == expected_value );
    }
}

int main() {
    DirectoryArray directory;
    directory.fill( -1 );
    test_fill( directory, -1 );
    return 0;
}

Использование массива требует использования«-std = c ++ 0x» для компиляции (относится к приведенному выше коду).

Если это недоступно или если это не опция, то другие опции, такие как std :: fill () (как предложено GMan ) или ручное кодирование a fill ()метод может быть выбран.

5 голосов
/ 23 мая 2010

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

boost::array<int,N> array; // boost arrays are of fixed size!
array.assign(-1);
5 голосов
/ 23 мая 2010

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

int x[3] = {-1, -1, -1 };

Вы также можете использовать вектор и использовать конструктор для инициализации всех значений. Позже вы можете получить доступ к буферу необработанного массива, указав &v.front()

std::vector directory(100, -1);

Существует способ C сделать это, также используя memset или различные другие подобные функции. memset работает для каждого символа в указанном вами буфере, хотя он будет работать нормально для значений, подобных 0, но может не работать в зависимости от того, как хранятся отрицательные числа для -1.


Вы также можете использовать STL для инициализации массива, используя fill_n . Для действий общего назначения с каждым элементом вы можете использовать for_each.

fill_n(directory, 100, -1);

Или, если вы действительно хотите, вы можете пойти неудачным путем, вы можете сделать цикл for с 100 итерациями и выполнить directory[i] = -1;

3 голосов
/ 23 мая 2010

Это работает правильно. Ваше ожидание инициализатора неверно. Если вы действительно хотите использовать этот подход, вам понадобится 100 разделенных запятыми -1 в инициализаторе. Но что происходит, когда вы увеличиваете размер массива?

2 голосов
/ 13 декабря 2016

У меня был тот же вопрос, и я нашел, как это сделать, в документации приведен следующий пример:

std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 (not in C++14)

Итак, я только что попробовал:

std::array<int, 3> a1{ {1} }; // double-braces required in C++11 (not in C++14)

И это работает, все элементы имеют 1 в качестве значения. Он не работает с оператором =. Возможно, это проблема C ++ 11.

1 голос
/ 01 сентября 2016

Вы просто используете для цикла, как сделано ниже: -

for (int i=0; i<100; i++)
{ 
a[i]= -1;
}

в результате, как вы хотите, вы можете получить A [100] = {- 1, -1, -1 .......... (100 раз)}

1 голос
/ 23 мая 2010

используйте вектор из int вместо массива.

vector<int> directory(100,-1);                       // 100 ints with value 1
1 голос
/ 23 мая 2010

Работает правильно. Вот как работают инициализаторы списка.

Я полагаю, что 6.7.8.10 стандарта C99 охватывает это:

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

  • если он имеет тип указателя, он инициализируется нулевым указателем;
  • если он имеет арифметический тип, он инициализируется как (положительный или без знака) ноль;
  • если это агрегат, каждый элемент инициализируется (рекурсивно) в соответствии к этим правилам;
  • если это объединение, первый именованный элемент инициализируется (рекурсивно) согласно этим правилам.

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

Также обратите внимание, что, если вы действительно не знаете, что делаете, векторы предпочтительнее массивов в C ++ :

Вот что вам нужно понять о контейнерах и массивах:

  1. Контейнерные классы делают программистов более продуктивными. Поэтому, если вы настаиваете на использовании массивов, в то время как окружающие готовы использовать контейнерные классы, вы, вероятно, будете менее продуктивными, чем они (даже если вы умнее и опытнее их!).
  2. Контейнерные классы позволяют программистам писать более надежный код. Поэтому, если вы настаиваете на использовании массивов, в то время как окружающие желают использовать контейнерные классы, ваш код, вероятно, будет содержать больше ошибок, чем их код (даже если вы умнее и опытнее).
  3. И если вы настолько умны и опытны, что можете использовать массивы так же быстро и безопасно, как они могут использовать контейнерные классы, кто-то другой, вероятно, в конечном итоге поддержит ваш код и, возможно, внесет ошибки. Или, что еще хуже, вы будете единственным, кто может поддерживать ваш код, так что руководство выдернет вас из разработки и переведет вас на постоянную работу по сопровождению - именно то, что вы всегда хотели!

Есть много вопросов к связанному вопросу; прочитайте.

0 голосов
/ 13 декабря 2017

Если вам разрешено использовать std :: array, вы можете сделать следующее:

#include <iostream>
#include <algorithm>
#include <array>
using namespace std;

template <class Elem, Elem pattern, size_t S, size_t L>
struct S_internal {
    template <Elem... values>
    static array<Elem, S> init_array() {
        return S_internal<Elem, pattern, S, L - 1>::init_array<values..., pattern>();
    }
};

template <class Elem, Elem pattern, size_t S>
struct S_internal<Elem, pattern, S, 0> {
    template <Elem... values>
    static array<Elem, S> init_array() {
        static_assert(S == sizeof...(values), "");
        return array<Elem, S> {{values...}};
    }
};

template <class Elem, Elem pattern, size_t S>
struct init_array
{
    static array<Elem, S> get() {
        return S_internal<Elem, pattern, S, S>::init_array<>();
    }
};

void main()
{
    array<int, 5> ss = init_array<int, 77, 5>::get();
    copy(cbegin(ss), cend(ss), ostream_iterator<int>(cout, " "));
}

Вывод:

77 77 77 77 77

...