Как использовать memset или fill_n для инициализации динамического двумерного массива в C++

У меня 2D массив создан динамически.

int **abc = new int*[rows];

for (uint32_t i = 0; i < rows; i++)
{
    abc[i] = new int[cols];
}

Я хочу заполнить массив некоторым значением (скажем, 1). Я могу перебрать каждый элемент и сделать это.

Но есть ли более простой способ. Я пытаюсь использовать memset а также std::fill_n как уже упоминалось в этом посте.

std::fill_n(abc, rows * cols, 1);
memset(abc, 1, rows * cols * sizeof(int));

Использование memset приводит к сбою моей программы. Использование fill_n дает ошибку компиляции.

invalid conversion from 'int' to 'int*' [-fpermissive]

Что я здесь не так делаю?

4 ответа

Решение

Вы могли бы просто использовать vector:

std::vector<std::vector<int>> abc(rows, std::vector<int>(cols, 1));

Вы не можете использовать std::fill_n или же memset на abc напрямую, это просто не будет работать. Вы можете использовать только один из под-массивов:

int **abc = new int*[rows];

for (uint32_t i = 0; i < rows; i++)
{
    abc[i] = new int[cols];
    std::fill_n(abc[i], cols, 1);
}

Или сделать все это одномерным:

int *abc = new int[rows * cols];
std::fill_n(abc, rows*cols, 1);

Или я думаю, вы могли бы использовать std::generate_n в комбинации с std::fill_n, но это только сбивает с толку:

int **abc = new int*[rows];
std::generate_n(abc, rows, [cols]{
    int* row = new int[cols];
    std::fill_n(row, cols, 1);
    return row;
});

Я думаю, что ваша главная проблема в том, что у вас нет массива int ценности. У вас есть множество указателей на ints.

Вы, вероятно, должны начать с int* abc = new int[rows * cols]; и работать оттуда, если я понимаю, что вы пытаетесь достичь здесь.

Просто используйте с * внутри цикла, который у вас уже есть:

for (uint32_t i = 0; i < rows; i++)
{
    abc[i] = new int[cols];
    std::fill_n(*(abc+i), cols, sizeof(int));
}

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

Рекомендую прочитать: правильный способ создания матрицы в с ++

Поскольку у вас уже есть хорошие, работоспособные ответы для решения вашей проблемы, я хочу добавить всего два указателя влево и вправо от стандартного пути;-)

а) это просто ссылка на документацию Boost.MultiArray

и б) это то, что я не рекомендую вам использовать, но это может помочь вам понять, что вы изначально пробовали. И так как ваш профиль показывает visual studio теги, вы можете вступить в контакт с чем-то вроде этого в API Win32. В этом случае документация обычно говорит вам не использовать free()/LocalFree()/... для элементов и "внешнего" указателя-указателя, а использовать специализированную функцию.
(примечание: я не пытаюсь сделать этот код красивым или умным; это путаница c и небольшого C++- бесполезный мусор;-))

const std::size_t rows = 3, cols =4; 

int main()
{   
    std::size_t x,y;
    // allocate memory for 0...rows-1 int* pointers _and_ cols*rows ints
    int **abc = (int**)malloc( (rows*sizeof(int*)) + cols*rows*sizeof(int) );

    // the memory behind abc is large enough to hold the pointers for abc[0...rows-1]
    // + the actual data when accessing abc[0...rows-1][0....cols-1]
    int* data = (int*)((abc+rows));
    // data now points to the memory right after the int*-pointer array
    // i.e. &(abc[0][0]) and data should point to the same location when we're done:
    // make abc[0] point to the first row (<-> data+(cols*0)), abc[1] point the second row (<-> data+(cols*1).... 
    for(y=0;y<rows; y++) {
        abc[y] = &(data[y*cols]);
    }

    // now you can use abc almost like a stack 2d array
    for(y=0; y<rows; y++) {
        for (x=0; x<cols; x++) {
            abc[y][x] = 127;
        }
    }

    // and -since the memory block is continuos- you can also (with care) use memset
    memset(&abc[0][0], 1, sizeof(int)*rows*cols);

    // and with equal care ....
    std::fill_n( &(abc[0][0]), rows*cols, 127);

    // and get rid of the whole thing with just one call to free
    free(abc);

    return 0;
}
Другие вопросы по тегам