c++ - std::byte 可以替换 std::aligned_storage 吗?

标签 c++ byte language-lawyer c++17

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 with t1?

没有。事实上,两者都不好。

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 most Len 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/

相关文章:

c++ - 在基本 ctor-initialiser 中将其强制转换为 `Derived*` 是否合法?

c++ - 绘制循环和 Lua (Luabridge)

javascript - JS 与 Python 字节数组编码

c - 外部链接内联函数定义是否需要 `extern`?

我可以将 NULL 传递给 modf/modff 吗?

c++ - 如何在函数导出上运行清理代码?

c++ - 将初始值设定项列表或集合作为参数

c - 在 C 中通过 TCP/IP 发送和接收字节数组

java - AES 加密 IV

c++ - 说一个C++对象是可 move 的,这到底意味着什么?