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

问题描述 投票:11回答:4

这是我正在使用的:

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

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

(更新:我之前应该已经明确表示我正在课堂上使用它。)

c++ multidimensional-array fill
4个回答
18
投票

初始化为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])在你的情况下是1sizeof(char)==1),但你可能想留在那里,以防你想在任何时候改变类型。

在这种特殊情况下(标志数组 - 整数类型)我甚至可以考虑使用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)更好的方法


2
投票

它是安全的,二维数组是一个数组数组。由于数组占用了连续的存储空间,所以整个多维事物也会如此。所以是的,没关系,安全和便携。假设你不是在问其他答案所涉及的风格(因为你正在使用旗帜,我强烈推荐std::vector<std::bitset<80> > myFlags(26)


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" /* ... */ };

-1
投票
char flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);
© www.soinside.com 2019 - 2024. All rights reserved.