为什么在C++23中不赞成使用std::aligned_storage?应该使用什么



我刚刚看到C++23计划弃用std::aligned_storagestd::aligned_storage_t以及std::aligned_unionstd::aligned_union_t

据我所知,在对齐存储中放置新对象对constexpr不是特别友好,但这似乎不是完全抛弃该类型的好理由。这让我认为,使用std::aligned_storage和朋友还有其他一些我不知道的根本问题。那会是什么?

有没有针对这些类型的替代方案?

以下是P1413R3:的三个摘录

背景

aligned_*对代码库有害,不应使用。高水平:

  • 使用aligned_*会调用未定义的行为(类型无法提供存储(
  • 保证是不正确的(标准只要求类型至少与要求的一样大,但没有对大小设置上限。(
  • API错误的原因很多(参见"On The API">(
  • 因为API是错误的,所以几乎所有的使用都涉及相同的重复前期工作(参见"现有使用"(

在API上

std::aligned_*受到许多API设计决策的不利影响。其中有些是共享的,有些是针对每个人的。至于共享内容,有三个主要问题[为了简洁起见,此处仅包含一个]

  • 需要使用reinterpret_cast来访问值

std::aligned_*实例上没有.data(),甚至没有.data。相反,API要求您获取对象的地址,用它调用reinterpret_cast<T*>(...),然后最后间接得到一个T&的指针。这不仅意味着它不能在constexpr中使用,而且在运行时,意外调用未定义的行为要容易得多。reinterpret_cast为使用要求API是不可接受的。


建议更换

aligned_*最简单的替换实际上不是库功能。相反,用户应该使用正确对齐的std::byte的数组,可能具有对std::max(std::initializer_list<T>)的调用。这些可以在<cstddef><algorithm>报头(示例在本节末尾(。不幸的是,这种替代并不理想。要访问aligned_*的值,用户必须在上调用reinterpret_cast读取字节作为CCD_ 26实例的地址。使用字节数组作为替换并不能避免这个问题。也就是说,重要的是要认识到,在reinterpret_cast已经存在的地方继续使用它,并不像在以前不存在的地方新引入它那么糟糕。。。

在已接受的退役aligned_*提案的上述部分之后,我们将举几个例子,如以下两个替换建议:

// To replace std::aligned_storage
template <typename T>
class MyContainer {
private:
//std::aligned_storage_t<sizeof(T), alignof(T)> t_buff;
alignas(T) std::byte t_buff[sizeof(T)];
};
// To replace std::aligned_union
template <typename... Ts>
class MyContainer {
private:
//std::aligned_union_t<0, Ts...> t_buff;
alignas(Ts...) std::byte t_buff[std::max({sizeof(Ts)...})];
};

最新更新