std :: byte可以代替std :: aligned_storage吗? [英] Can std::byte replace std::aligned_storage?

查看:201
本文介绍了std :: byte可以代替std :: aligned_storage吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 17引入了一种新类型, std :: byte ,所以现在我们终于有了一个一流的市民类型来表示内存中的字节。除了标准上的新颖性之外,用于对象创建,生命周期的开始和结束,别名等的C ++规则在大多数时候都是相当不直观的,因此,每当我感到 std :: byte 是正确的工具,我也会感到紧张和不愿使用它,因为担心会无意间召唤未定义的行为Balrogs。

C++17 introduced a new type, std::byte, so now we finally have a first-class citizen type to represent bytes in memory. Besides being a novelty in the standard, the C++ rules for object creation, start and end of life, aliasing etc. are fairly complicated an unintuitive most of the times, so whenever I feel std::byte is the right tool I also get nervous and reluctant to use it, for fear of unintentionally summoning the Undefined Behavior Balrogs.

一个这样的情况就是缓冲区与新的展示位置一起使用:

One such case is a buffer to be used with placement 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();
}

t2 完美并与 t1 等价?

针对对齐问题,该怎么办:

In response to alignment issues, what about:

auto t3()
{
    alignas(X) std::byte buffer[sizeof(X)];

    X* x = new (&buffer) X{};
    x->~X();
}


推荐答案


t2 是否完全安全并且与 t1 等效?

Is t2 perfectly safe and equivalent with t1?

否实际上,两者都是不好的。

No. In fact, both are bad.

t2 不好,原因是NathanOliver 表示:未对齐。您需要编写:

t2 is bad for the reason NathanOliver indicates: it's underaligned. You'd need to write:

alignas(X) std::byte storage[sizeof(X)];

t1 也有这个问题,因为您几乎肯定要写 aligned_storage_t< sizeof(X),alignof(X)> 而不仅仅是 aligned_storage_t< sizeof(X)> ; 。如果 X 被过度对齐,您将在这里丢失它。如果 X 很大,但没有对齐要求,则最终将导致相对对齐的存储空间。

t1 also kind of has this problem, in that you almost certainly want to write aligned_storage_t<sizeof(X), alignof(X)> and not just aligned_storage_t<sizeof(X)>. If X were overaligned, you would lose that here. If X was just large but had no alignment requirement, you would end up with a relatively overaligned storage.

t1 也是不好的一个特殊原因: aligned_storage 并不能完全保证您认为的保证。特别是,它保证 X 可以适合 aligned_storage< sizeof(X)> ,但不能这样做确保它完全适合 规范只是:

t1 is also bad for an especially peculiar reason: aligned_storage doesn't quite guarantee what you think it guarantees. In particular, it guarantees that an X can fit in aligned_storage<sizeof(X)>, but it does not guarantee that it can fit exactly. The specification is simply:


成员typedef type 应该是普通的标准布局类型,适合用作任何对象的未初始化存储其大小最大为 Len ,并且其对齐方式是Align的除数。

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> 的问题。

That is, aligned_storage<16>::type is guaranteed to be at least 16 bytes, but a conforming implementation could easily give you 32. Or 4K. That in addition to the problem of using aligned_storage<16> by accident instead of aligned_storage_t<16>.

这就是为什么 P1413 作为论文存在的原因: aligned_storage 有点不好。

This is why P1413 exists as a paper: aligned_storage is kind of bad.

因此,真正的答案实际上只是写像libstdc ++的 __ aligned_membuf

So the real answer is actually just to write something like libstdc++'s __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*
};

这篇关于std :: byte可以代替std :: aligned_storage吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆