17

这是我正在使用的:

class something
{
   char flags[26][80];
} a;

std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);

(更新:我应该早先明确表示我在课堂上使用它。)

4

5 回答 5

31

初始化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(flags[0][0])情况1下 ( sizeof(char)==1),但您可能希望将其保留在那里,以防您想随时更改类型。

在这种特殊情况下(标志数组--integral 类型)我什至可以考虑使用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是公开的,使用构造函数可能是更好的方法,因为它可以保证array在类的所有实例中正确初始化,而外部初始化取决于用户代码不要忘记设置初始值。

[1] 正如@Oli Charlesworth 在评论中提到的那样,使用常量是解决必须在多个地方声明(并保持同步)大小问题的不同解决方案。我在这里使用了另一种不同的组合方法:可以通过请求二维数组之外的第一列的地址来获得指向二维数组之外的第一个字节的指针。我使用这种方法只是为了表明它可以完成,但它并不比其他人更好&array[0][0]+(rows*cols)

于 2010-10-16T09:21:13.843 回答
4

使用填充多维数组的安全方法是什么std::fill

简单的默认初始化将使用大括号 inilization

char flags[26][80]{};

上面会将所有元素初始化flags为默认字符。


std::fill使用或填充二维数组std::fill_n

但是,为了提供不同的值来初始化以上是不够的。选项是std::fillstd::fill_n。(假设该数组flagspublic您的班级中)

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

现在你可以初始化你的flagslike

fill_2D_array(a.flags, '0'); // flags should be `public` in your class!

见在线直播


std::fill使用或填充 3-D 阵列std::fill_n

在上面的模板函数中再添加一个非模板大小参数,这也可以带入3d-array s

#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);
}

见在线直播

于 2020-08-08T12:18:38.120 回答
2

它是安全的,二维数组是数组的数组。由于数组占用了连续的存储空间,所以整个多维的东西也会。所以,是的,它没关系,安全且便携。假设您没有询问样式,其他答案已涵盖了样式(因为您使用的是标志,我强烈建议您std::vector<std::bitset<80> > myFlags(26)

于 2010-10-16T09:17:24.633 回答
1
char flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);
于 2018-09-02T04:32:55.540 回答
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" /* ... */ };
于 2010-10-16T10:25:26.097 回答