我正在使用以下内容:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);
(更新:我之前应该清楚地说明我是在类中使用这个函数的。)
我正在使用以下内容:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);
(更新:我之前应该清楚地说明我是在类中使用这个函数的。)
初始化数组为 0
的简单方法是在定义时进行:
char flags[26][80] = {};
如果你想使用std::fill
,或者你想要重置这个数组,我认为这样会更好:
char flags[26][80];
std::fill( &flags[0][0], &flags[0][0] + sizeof(flags) /* / sizeof(flags[0][0]) */, 0 );
通过以数组大小为参考的fill
,你可以更改维度并保持fill
不变。在你的情况下(sizeof(char) == 1
),sizeof(flags[0][0])
为1
,但你可能希望保留它,以便在任何时候可以更改类型。
在这种特殊情况下(整数类型的flags数组),即使它是最不安全的选择,我甚至也可以考虑使用memset
(如果将数组类型更改为非POD类型,则会出现错误):
memset( &flags[0][0], 0, sizeof(flags) );
需要注意的是,在这三种情况下,数组大小只需声明一次,编译器会自动推断其余部分。这种方式更加安全,因为这样可以减少程序员错误(在一个地方更改大小,却忘记在其他地方修改)。
编辑:你已经更新了代码,但它无法编译,因为数组是私有的,并且你试图从外部初始化它。根据你的类实际上是否是聚合的(并且想保持为聚合),或者是否要向类中添加构造函数,可以采用不同的方法。
const std::size_t rows = 26;
const std::size_t cols = 80;
struct Aggregate {
char array[rows][cols];
};
class Constructor {
public:
Constructor() {
std::fill( &array[0][0], &array[rows][0], 0 ); // [1]
// memset( array, 0, sizeof(array) );
}
private:
char array[rows][cols];
};
int main() {
Aggregate a = {};
Constructor b;
}
即使数组预计是公共的,使用构造函数可能是更好的方法,因为它将保证在类的所有实例中正确初始化数组,而外部初始化取决于用户代码不要忘记设置初始值。&array[0][0]+(rows*cols)
并没有任何区别。如何使用
std::fill
安全地填充多维数组?
简单的默认初始化方法是 使用大括号初始化。
char flags[26][80]{};
flags
中的所有元素初始化为默认字符。
std::fill
或std::fill_n
填充二维数组然而,仅提供以上初始化值是不够的。可选的方法有std::fill
和std::fill_n
。(假设数组flags
在您的类中为public
)
std::fill(
&a.flags[0][0],
&a.flags[0][0] + sizeof(a.flags) / sizeof(a.flags[0][0]),
'0');
// or using `std::fill_n`
// std::fill_n(&a.flags[0][0], sizeof(a.flags) / sizeof(a.flags[0][0]), '1');
sizeof
。#include <algorithm> // std::fill_n, std::fill
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N>
constexpr void fill_2D_array(Type(&arr2D)[M][N], const Type val = Type{}) noexcept
{
std::fill_n(&arr2D[0][0], M * N, val);
// or using std::fill
// std::fill(&arr2D[0][0], &arr2D[0][0] + (M * N ), val);
}
flags
:fill_2D_array(a.flags, '0'); // flags should be `public` in your class!
(在线查看)
std::fill
或std::fill_n
填充3-D数组将上述模板函数添加一个非模板大小参数,即可将其应用于三维数组
#include <algorithm> // std::fill_n
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N, std::size_t O>
constexpr void fill_3D_array(Type(&arr3D)[M][N][O], const Type val = Type{}) noexcept
{
std::fill_n(&arr3D[0][0][0], M * N * O, val);
}
(在线观看)
安全性是可以保证的, 二维数组是由数组组成的数组。由于数组占用连续的存储空间,所以整个多维数组也将如此。因此,是的,它是可以使用的,安全和可移植的。假设您不是在询问样式,这已经被其他答案涵盖(由于您正在使用标志,强烈建议使用std::vector<std::bitset<80> > myFlags(26)
)
(row,col)->index
代数,使用单个bitset
将更有效地消耗内存。 - David Rodríguez - dribeaschar flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);
char[80]
是用来替代真正的字符串类型吗?如果是的话,我建议使用以下方式:
std::vector<std::string> flags(26);
flags[0] = "hello";
flags[1] = "beautiful";
flags[2] = "world";
// ...
或者,如果您有支持初始化列表的C++编译器,例如最近的g++编译器:
std::vector<std::string> flags { "hello", "beautiful", "world" /* ... */ };
fill(&arr[0], &arr[0] + sizeof(arr), 0)
在一维数组中不起作用吗? - Dhruv Mullicksizeof
运算符会给出以字节为单位的大小,而不是元素数量。如果arr
包含任何使得sizeof(*arr) != 1
的内容,则上述代码行为未定义,并且可能会导致崩溃(尝试访问数组末尾之外的位置)。否则(即如果数组包含[unsigned|signed] char
),它应该可以正常工作。 - David Rodríguez - dribeasfill
函数的第二个参数不应该是&array[rows][cols]
吗? - 463035818_is_not_a_number&array[rows][cols]
是整个数组的最后一个元素所在的一整行,而不仅仅是超出一个元素。 - David Rodríguez - dribeas