我正在处理哈希表,并且我有一个包含我的键值的存储桶类型,所以我可以将它们保存在联合中并保持未初始化以避免为它们要求DefaultConstructible:
template <class K, class V>
struct bucket {
bucket() : hash(SENTINEL) {}
bucket(uint64_t hash, K&& k, V&& v)
: hash(hash), key(std::forward(k)), val(std::forward(v)) {}
<copy constructors>
~bucket() {
if (hash != SENTINEL) {
key.~K();
val.~V();
}
}
uint64_t hash;
union { K key; }
union { V key; }
};
那么,我的问题就像是=运算符,我通常会用复制和交换习语写出来:
bucket& operator =(bucket other) {
using std::swap;
swap(hash, other,hash);
swap(key, other.key);
swap(val, other.val);
}
这是否仍然安全,即使使用了单位化的键和val?
答案 0 :(得分:5)
这甚至更早失败:读取除最后一个成员之外的union
成员是UB。
如果您尚未为任何会员分配值,您也无法阅读任何会员,无论其类型或任何&#34;阅读未经注册的变量&#34;规则。
正如我在评论中提到的,避免默认可构造要求的正确方法是使用新的位置。