C++17 引入了一个新类型,std::byte
,所以现在我们终于有了一个一等公民类型来表示内存中的字节。除了标准中的新颖性之外,对象创建、生命周期的开始和结束、别名等的 C++ 规则在大多数时候都相当复杂且不直观,所以每当我觉得 std::byte
是正确的工具我也很紧张,不愿意使用它,因为害怕无意中召唤未定义行为的炎魔。
一个这样的例子是用于放置新的缓冲区:
#include <memory>
#include <cstddef>
#include <type_traits>
struct X { double dummy[4]; char c; };
auto t1()
{
// the old way
std::aligned_storage_t<sizeof(X)> buffer;
X* x = new (&buffer) X{};
x->~X();
}
auto t2()
{
// the new way?
std::byte buffer[sizeof(X)];
X* x = new (&buffer) X{};
x->~X();
}
t2
是否完全安全并且等同于 t1
?
针对对齐问题,怎么样:
auto t3()
{
alignas(X) std::byte buffer[sizeof(X)];
X* x = new (&buffer) X{};
x->~X();
}
最佳答案
Is
t2
perfectly safe and equivalent witht1
?
没有。事实上,两者都不好。
t2
不好的原因NathanOliver表示:未对齐。你需要写:
alignas(X) std::byte storage[sizeof(X)];
t1
也有点这个问题,因为你几乎肯定想写 aligned_storage_t<sizeof(X), alignof(X)>
而不仅仅是 aligned_storage_t<sizeof(X)>
.如果X
过度对齐,你会在这里失去它。如果X
只是很大但没有对齐要求,你最终会得到一个相对过度对齐的存储。
t1
由于一个特别特殊的原因也很糟糕:aligned_storage
并不能完全保证你认为它能保证什么。特别是,它保证 X
可以放入 aligned_storage<sizeof(X)>
,但不保证它可以完全。 specification很简单:
The member typedef
type
shall be a trivial standard-layout type suitable for use as uninitialized storage for any object whose size is at mostLen
and whose alignment is a divisor of Align.
即aligned_storage<16>::type
保证至少为 16 个字节,但符合要求的实现很容易为您提供 32 个或 4K。那除了使用的问题aligned_storage<16>
意外而不是aligned_storage_t<16>
.
这就是为什么 P1413作为论文存在:aligned_storage
有点糟糕。
所以真正的答案实际上只是写一些类似 libstdc++ 的 __aligned_membuf
的东西:
template <typename T>
struct storage_for {
alignas(T) std::byte data[sizeof(T)];
// some useful constructors and stuff, probably some getter
// that gives you a T* or a T const*
};
关于c++ - std::byte 可以替换 std::aligned_storage 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58288225/