gpt4 book ai didi

c++ - C++20 中的 std::launder 用例

转载 作者:行者123 更新时间:2023-12-01 14:22:48 26 4
gpt4 key购买 nike

[1]

有没有添加p0593r6的情况转化为 C++20(第 6.7.2.11 节对象模型 [intro.object])制作 std::launder没有必要,在 C++17 中需要相同的用例 std::launder ,还是它们完全正交?

[2]

[ptr::launder] 规范中的示例是:

struct X { int n; };
const X *p = new const X{3};
const int a = p->n;
new (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const
const int b = p->n; // undefined behavior
const int c = std::launder(p)->n; // OK

另一个例子是@Nicol Bolas in this SO answer ,使用指向有效存储但类型不同的指针:
aligned_storage<sizeof(int), alignof(int)>::type data;
new(&data) int;
int *p = std::launder(reinterpret_cast<int*>(&data));

是否还有其他用例,与允许转换两个不是 transparently replaceable 的对象无关, 用于使用 std::launder ?

具体来说:
  • 将 reinterpret_cast 从 A* 到 B*,两者都是 pointer-interconvertible , 可能需要使用 std::launder任何状况之下? (即两个指针可以是指针可互转换的,但不能透明地替换吗?规范在这两个术语之间没有关联)。
  • 是否 reinterpret_cast 来自 void*到 T* 需要使用 std::launder ?
  • 下面的代码是否需要使用 std::launder ?如果是这样,在规范中的哪种情况下需要这样做?

  • 一个带有引用成员的结构,灵感来自 this discussion :
    struct A {
    constexpr A(int &x) : ref(x) {}
    int &ref;
    };

    int main() {
    int n1 = 1, n2 = 2;
    A a { n1 };
    a.~A();
    new (&a) A {n2};
    a.ref = 3; // do we need to launder somebody here?
    std::cout << a.ref << ' ' << n1 << ' ' << n2 << std::endl;
    }

    最佳答案

    在 C++17 之前,具有给定地址和类型的指针总是 指向 位于该地址的该类型的对象,前提是代码遵守 [basic.life] 的规则。 (见:Is a pointer with the right address and type still always a valid pointer since C++17?)。
    但是在 C++17 标准中,为指针值添加了新的特性。这种质量不是在指针类型内编码,而是直接限定值,独立于类型(这也是可追溯性的情况)。它在 [basic.compound]/3 中有描述

    Every value of pointer type is one of the following:

    • a pointer to an object or function (the pointer is said to point to the object or function), or

    • a pointer past the end of an object ([expr.add]), or

    • the null pointer value for that type, oran invalid pointer value.


    指针值的这种特性有它自己的语义(转换规则),对于 reinterpret_cast 的情况。它在下一段中描述:

    If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast.


    在 [basic-life] 中,我们可以找到另一个规则来描述当对象存储被重用时如何转换这种质量:

    If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, [...]


    如您所见,质量“指向对象的指针”附加到特定对象。
    这意味着在您给出的第一个示例的变体中, reinterpret_cast不允许我们不使用指针优化屏障:
    struct X { int n; };
    const X *p = new const X{3};
    const int a = p->n;
    new (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const
    const int b = *reinterpret_cast <int*> (p); // undefined behavior
    const int c = *std::launder(reinterpret_cast <int*> (p));
    一个 reinterpret_cast不是指针优化障碍: reinterpret_cast <int*>(p)指向被销毁对象的成员。
    另一种设想它的方式是“指向”质量由 reinterpret_cast 保存。只要对象是指针可相互转换的,或者如果将其强制转换为 void 然后返回指针可相互转换的类型。 (见 [exp.static_cast]/13)。所以 reinterpret_cast <int*>(reinterpret_cast <void*>(p))仍然指向被销毁的对象。
    对于您给出的最后一个示例,名称 a指的是一个非 const 完整对象,所以原来的 a可以透明地替换为新对象。

    对于 第一个问题你问:“是否有任何情况下将 p0593r6 添加到 C++20(第 6.7.2.11 节对象模型 [intro.object])使得 std::launder 不再需要,在 C++17 中的相同用例需要 std::launder,还是它们完全正交?”
    老实说,我找不到任何 std::launder 可以补偿隐式生命周期对象的情况。但我发现一个例子是隐式生命周期对象使 std::launder 有用:
      class my_buffer {
    alignas(int) std::byte buffer [2*sizeof(int)];

    int * begin(){
    //implictly created array of int inside the buffer
    //nevertheless to get a pointer to this array,
    //std::launder is necessary as the buffer is not
    //pointer inconvertible with that array
    return *std::launder (reinterpret_cast <int(*)[2]>(&buffer));
    }
    create_int(std::size_t index, int value){
    new (begin()+index) auto{value};
    }
    };

    关于c++ - C++20 中的 std::launder 用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62114622/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com