我有一类,其目的是将可能具有对齐限制的数据移入或移出未对齐数据的串行化内存缓冲区。我已设置并获取处理程序,如下所示:
#include <cstring>
template<typename T>
struct handle_type {
static inline T get(const void *data) {
T value;
memcpy(&value, data, sizeof(T));
return value;
}
static inline void set(void *data, T value) {
memcpy(data, &value, sizeof(T));
}
};
在c ++ 20发布之后,我希望它将变成如下所示:
#include <bit>
template<typename T>
struct handle_type {
union unaligned { char bytes[sizeof(T)]; }; // EDIT: changed from struct
static inline T get(const void *data) {
return std::bit_cast<T>(*(const unaligned*)data);
}
static inline void set(void *data, T value) {
*(unaligned *)data = std::bit_cast<unaligned>(value);
}
};
能行吗还是我使用的是惯性类型(不对齐的结构类型)容易引起问题?
最佳答案
除非用户提供了指向get
对象的指针,否则您的unaligned
函数是UB。除非set
是data
对象,否则unaligned
函数类似于UB。这两种情况均违反严格的别名。请记住:严格的别名后门是关于实际的char*
;这与碰巧包含char*
的对象不同。
同样,set
可能是编译错误,这完全取决于unaligned
的实现是否与T
相同。毕竟,unaligned
可能在末尾有填充。bit_cast
主要要处理对象,而不是内存的随机缓冲区。为此,您应该坚持使用memcpy
。
union代替>
那什么都没改变;使用struct
不能保证union
的大小等于其最大数据成员的大小。从[class.union] / 2:
联合的大小足以容纳其最大的非静态数据成员。
重点补充:“足够”,而不是“等于”。该标准允许实现使联合的大小大于其最大数据成员的能力,因为这样的大小仍然是“足够的”。