C++ 使用 std::fill 填充多维数组的安全方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3948290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
what's the safe way to fill multidimensional array using std::fill?
提问by Truncheon
Here's what I'm using:
这是我正在使用的:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0]+26*80, 0);
(Update: I should have made it clear earlier that I'm using this inside a class.)
(更新:我应该早点说清楚我在课堂上使用它。)
回答by David Rodríguez - dribeas
The simple way to initialize to 0
the array is in the definition:
初始化0
数组的简单方法在定义中:
char flags[26][80] = {};
If you want to use std::fill
, or you want to resetthe array, I find this a little better:
如果你想使用std::fill
,或者你想重置数组,我觉得这更好一点:
char flags[26][80];
std::fill( &flags[0][0], &flags[0][0] + sizeof(flags) /* / sizeof(flags[0][0]) */, 0 );
The fill
expressed in terms of the array size will allow you to change the dimensions and keep the fill
untouched. The sizeof(flags[0][0])
is 1
in your case (sizeof(char)==1
), but you might want to leave it there in case you want to change the type at any point.
将fill
在阵列尺寸方面将允许您更改尺寸,并保持表达fill
不变。该sizeof(flags[0][0])
是1
你的情况(sizeof(char)==1
),但你可能想在那里把它留在你想在任何时候更改类型案件。
In this particular case (array of flags--integral type) I could even consider using memset
even if it is the least safealternative (this will break if the array type is changed to a non-pod type):
在这种特殊情况下(标志数组--integral 类型),我什至可以考虑使用,memset
即使它是最不安全的替代方案(如果将数组类型更改为非 pod 类型,这将中断):
memset( &flags[0][0], 0, sizeof(flags) );
Note that in all three cases, the array sizes are typed only once, and the compiler deduces the rest. That is a little saferas it leaves less room for programmer errors (change the size in one place, forget it in the others).
请注意,在所有三种情况下,数组大小只输入一次,编译器会推断其余部分。这更安全一点,因为它为程序员错误留下了更少的空间(在一个地方改变大小,在其他地方忘记它)。
EDIT: You have updated the code, and as it is it won't compile as the array is private and you are trying to initialize it externally. Depending on whether your class is actually an aggregate (and want to keep it as such) or whether you want to add a constructor to the class you can use different approaches.
编辑:您已经更新了代码,因为它不会编译,因为数组是私有的,并且您正在尝试在外部对其进行初始化。根据您的类是否实际上是一个聚合(并希望保留它)或者您是否想向类添加构造函数,您可以使用不同的方法。
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;
}
Even if the array
is meant to be public, using a constructor might be a better approach as it will guarantee that the array
is properly initialized in all instances of the class, while the external initialization depends on user code not forgetting to set the initial values.
即使array
是公开的,使用构造函数可能是更好的方法,因为它可以保证array
在类的所有实例中正确初始化,而外部初始化取决于用户代码不要忘记设置初始值。
[1] As @Oli Charlesworth mentioned in a comment, using constants is a different solution to the problem of having to state (and keep in synch) the sizes in more than one place. I have used that approach here with a yet different combination: a pointer to the first byte outside of the bidimensional array can be obtained by requesting the address of the first column one row beyond the bidimensional array. I have used this approach just to show that it can be done, but it is not any better than others like &array[0][0]+(rows*cols)
[1] 正如@Oli Charlesworth 在评论中提到的那样,对于必须在多个地方声明(并保持同步)大小的问题,使用常量是一种不同的解决方案。我在这里使用了一种具有不同组合的方法:通过请求二维数组之外一行的第一列的地址,可以获得指向二维数组外第一个字节的指针。我使用这种方法只是为了表明它可以完成,但它并不比其他方法好&array[0][0]+(rows*cols)
回答by Armen Tsirunyan
it is safe, a two-dimensional array is an array of arrays. Since an array occupied contiguous storage, so the whole multidimensional thing will too. So yeah, it's OK, safe and portable. Assuming you are NOT asking about style, which is covered by other answers (since you're using flags, I strongly recommend std::vector<std::bitset<80> > myFlags(26)
)
它是安全的,二维数组是数组的数组。由于一个数组占用了连续的存储空间,所以整个多维的东西也会如此。所以是的,没关系,安全且便携。假设您不是在问其他答案所涵盖的样式(因为您使用的是标志,我强烈推荐std::vector<std::bitset<80> > myFlags(26)
)
回答by fredoverflow
Is char[80]
supposed to be a substitute for a real string type? In that case, I recommend the following:
被char[80]
认为是一个真正的字符串类型的替代品?在这种情况下,我建议如下:
std::vector<std::string> flags(26);
flags[0] = "hello";
flags[1] = "beautiful";
flags[2] = "world";
// ...
Or, if you have a C++ compiler that supports initialization lists, for example a recent g++ compiler:
或者,如果您有一个支持初始化列表的 C++ 编译器,例如最近的 g++ 编译器:
std::vector<std::string> flags { "hello", "beautiful", "world" /* ... */ };
回答by Hongfei Shen
char flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);