c++ - 将数组的一部分有效地设置为零

标签 c++ arrays memset

我试图将简单对象的数组重置为零,如下所示:

using Node = std::array<std::uint16_t, 256>;
using Array = std::array<Node, 4096>;

void reset_1(Array& a) {
  std::fill(std::begin(a), std::end(a), Node{});
}
    
void reset_2(Array& a) {
  a = {};
}

void reset_3(Array& a) {
  a.fill(Node{});
}
所有这些功能都可以完成工作,但是查看编译器浏览器(同时使用Clang 10.0.1和gcc 10.2),reset_2在一个memset中完成它,而其他两个在多个块中完成(使用std::fill_n同样的结果)。
在我的真实情况下,我实际上想重置所有节点,除了第一个节点。这将导致我编写如下内容:
void reset_not_zero_1(Array& a) {
  std::fill(std::begin(a) + 1, std::end(a), Node{});
}
    
void reset_not_zero_2(Array& a) {
  std::memset(a.data() + 1, 0, sizeof(a) - sizeof(Node));
}
我的问题是:我是否使用reset_not_zero_2调用某种未定义的行为?该数组是可复制的,但也许我缺少了一些东西。

最佳答案

cppreference

Converts the value ch to unsigned char and copies it into each of the first count characters of the object pointed to by dest. If the object is a potentially-overlapping subobject or is not TriviallyCopyable (e.g., scalar, C-compatible struct, or an array of trivially copyable type), the behavior is undefined. If count is greater than the size of the object pointed to by dest, the behavior is undefined.


到现在为止还挺好。
假设另一个节点大小为14,但其alignas为16
using Array = std::array<Node, 4096>;
然后,“a”的大小将为16 * 4096 = 65536,因为Node将强制填充2。
std::memset(a.data() + 1, 0, sizeof(a) - sizeof(Node));
然后,这将是65536-16字节中的65536-14,这不行,因为它将覆盖2个字节的下一个数据。
另一方面
sizeof(a) == a.size()*sizeof(a::value_type) 
那应该没问题。
同样,如果将alignas强制使用更大的尺寸,也应该可以。

关于c++ - 将数组的一部分有效地设置为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64242788/

相关文章:

c - Linux 内核从 kzalloc 取消引用 memset 中的 NULL 指针

c++ - 用模板类完美转发

C++:#pragma comment(lib, "XXX") 实际上对 "XXX"做了什么?

c - 未初始化字符数组的 %d 说明符

javascript - 使用 Array.prototype.findIndex() 查找对象

c - memset 不起作用 (C)

c++ - 为什么没有发生堆栈溢出?

c++ - 类型 `*` 对 __vfptr 意味着什么?

c++ - 将 kleene 运算符解析为一组替代方案,适配器?有精神x3

php - mysql使用二维数组存储数据