如何使用memset或fill_n在C++中初始化动态二维数组

6

我有一个动态创建的二维数组。

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

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

我想用一些值(比如1)填充数组。我可以遍历每个元素并执行此操作。
但是是否有更简单的方法?我正在尝试使用memsetstd::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]

我在这里做错了什么吗?

退回到C可能是一个选择:int (*abc)[cols]=malloc(rows*sizeof(*abc)); memset(abc, 1, rows*sizeof(*abc)); 是合法的C代码,自从C99以来,但在相当一段时间内在C++中是不可行的。 - cmaster - reinstate monica
4个回答

6

你可以直接使用vector

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

你不能直接在abc上使用std::fill_n或者memset,这样做是不会起作用的。你只能在子数组上使用其中之一:

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_nstd::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;
});

3
我认为你的主要问题在于你没有一个 int 值的数组。你有一个指向 int 的指针数组。
如果我理解你在这里想要实现什么,你应该从 int* abc = new int[rows * cols]; 开始,并从那里开始工作。

2

只需在您已经拥有的循环中使用 * 即可:

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

fill_n不知道新的int数组被映射到哪里的内存,因此您必须小心编写代码。

我建议阅读: 在C++中创建矩阵的正确方法


1

既然你已经得到了解决问题的好答案,我想从标准路径左右两个指针中添加两个指针 ;-)

a) 只是一个指向 Boost.MultiArray 文档的链接

b) 是我不建议你使用的东西,但它可能会帮助你理解你最初尝试过的东西。由于你的个人资料显示出visual studio标签,你可能会接触到类似于win32 api的东西。如果是这样,文档通常会告诉你不要在元素和“外部”指针-指针上使用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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接