C++17引入了一种新类型,std::byte
,所以现在我们终于有了一个一等公民类型来表示内存中的字节。除了在标准中是一个新颖的东西之外,C++ 的对象创建、生命周期的开始和结束、别名等规则在大多数情况下都相当复杂且不直观,所以每当我觉得std::byte
是正确的工具我也感到紧张并且不愿意使用它,因为担心无意中召唤未定义行为炎魔。
其中一种情况是与放置 new 一起使用的缓冲区:
#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();
}
Is t2
完全安全且等同于t1
?
针对对齐问题,如何:
auto t3()
{
alignas(X) std::byte buffer[sizeof(X)];
X* x = new (&buffer) X{};
x->~X();
}
Is t2
完全安全且等同于t1
?
不,事实上,两者都不好。
t2
是坏的原因内森·奥利弗表示:未对齐。你需要写:
alignas(X) std::byte storage[sizeof(X)];
t1
也有这个问题,因为你几乎肯定想写aligned_storage_t<sizeof(X), alignof(X)>
不仅仅是aligned_storage_t<sizeof(X)>
. If X
过度对齐,你会在这里失去它。如果X
只是很大但没有对齐要求,您最终会得到相对过度对齐的存储。
t1
由于一个特别特殊的原因也很糟糕:aligned_storage
并不能完全保证您认为它保证的内容。特别是,它保证X
可以适应aligned_storage<sizeof(X)>
,但不保证能适合exactly. The 规格简单来说就是:
成员 typedeftype
应是一个简单的标准布局类型,适合用作大小最多为任何对象的未初始化存储Len
其对齐方式是 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*
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)