使用枚举类类型(C++11)初始化一个二维 std::array。

7

我有一个在C++11中的类:

class MyTable
{
    public:
    enum class EntryType
    {
        USED, FREE
    };

    MyTable(EntryType value)
    {
        for (uint32_t i = 0; i < 10; ++i)
        {
            memset(_table[i].data(), (int)value, sizeof(_table[0][0]) * 50);
        }
    }
    array<array<EntryType, 50>, 10> _table;
}

尝试使用EntryType::FREE构造MyTable对象时,二维数组中每个项目的值都为0x01010101(每8位1b),而不是预期的0x1。我猜测这与我的"value"被强制转换为"int"有关,但我不知道该怎么做才能解决它。

1
为什么你要使用memset来初始化值,而不是直接赋值呢? - πάντα ῥεῖ
3
这就是memset函数的作用,它逐字节地进行初始化。 - Kinan Al Sarmini
只需使用手动初始化。如果您尝试通过memset()1设置为int类型,它将是0x01010101,这是定义行为。 - renzo
你的实现不是很内存高效,如果你不需要32位枚举,可以使用uint8_t数组,这样你的memset()调用就会成功。 - gabry
@gabry 你说得没错,但是内存对于我当前的任务不是问题。 - itzhaki
实现定义的行为,你的意思是?sizeof(int)并不一定是16位,正如该十六进制模式所暗示的那样。 - underscore_d
2个回答

6

memset()被期望按照以下方式工作,因为它的作用是:

将目标缓冲区的每个字节设置为指定的值。

更多信息,请参见为什么memset()错误地初始化int?

但是要小心,因为正如juanchopanza所说,std::array可能在结尾处填充了空间(请查看std::array对齐),这意味着这种方法可能会失败。


由于这是一个二维数组,您可以使用基于范围的for循环和std::array::fill,如下所示:

for(auto& row : _table)
    row.fill(value);

如Renzo所述。

如果您不想将每一行都设置为相同的值,当然可以这样做:

for(auto &row : array)
    for(auto &col : row)
         col = value; 

多维数组上使用基于范围的for循环方面,欲知更多,请点击链接。


1
可以使用基于范围的for循环。 - The Techel
或者另一种变体:for(auto& array : _table) array.fill(value); - renzo
1
std::array 可能在末尾有填充,因此在 OP 代码中使用 memset 不能保证有效。 - juanchopanza
@juanchopanza 哦,谢谢你,我不知道那个!感谢 The Techel 和 renzo 的建议,它们真的改善了答案!=) - gsamaras
1
这解决了我的问题,感谢您详细的回复。memset 中的 int 让我困惑了,因为我不知道它被转换为 unsigned char - itzhaki
@juanchopanza(尽管我认为在那里放置填充的实现方式很愚蠢)为什么在结尾处添加填充会对此有任何影响?memset将从开头执行到最后一个元素,包括最后一个元素。最后一个元素之后的填充不应被读取或更改,因此它不应该有任何影响。 - underscore_d

3
这可以通过使用基于范围的for循环和std::array::fill成员函数来完成。
MyTable(EntryType value)
{
    for (auto& row : _table) {
        row.fill(value);
    }
}

即使您更改数组的维度,此功能仍将继续正常工作。

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