C++ std::vector的所有实现在std::launder之前都是不可移植的吗?

C++ std::vector的所有实现在std::launder之前都是不可移植的吗?,c++,c++11,language-lawyer,placement-new,C++,C++11,Language Lawyer,Placement New,在std::vector实例上调用emplace\u back()时,将在先前分配的存储中创建一个对象。这可以很容易地实现与新的位置,这是完美的便携式。 但是现在,我们需要在不调用未定义行为的情况下访问已放置的元素 从 我知道有两种方法可以做到这一点 使用placement new返回的指针: auto*elemPtr=new(bufferPtr)MyType() 或者,从C++17开始,指针从bufferPtr auto*elemPtr2=std::流槽(重新解释强制转换(bufferPtr

std::vector
实例上调用
emplace\u back()
时,将在先前分配的存储中创建一个对象。这可以很容易地实现与新的位置,这是完美的便携式。 但是现在,我们需要在不调用未定义行为的情况下访问已放置的元素

从 我知道有两种方法可以做到这一点

  • 使用placement new返回的指针:
    auto*elemPtr=new(bufferPtr)MyType()

  • 或者,从C++17开始,指针从
    bufferPtr

    auto*elemPtr2=std::流槽(重新解释强制转换(bufferPtr))

  • 第二种方法很容易推广到我们有很多对象的情况 放置在相邻的内存位置,如
    std::vector
    。但是在C++17之前人们做了什么? 一种解决方案是将放置新位置返回的指针存储在单独的动态数组中。 虽然这当然是合法的,但我认为它并没有真正实现std::vector[此外,单独存储我们已经知道的所有地址是一个疯狂的想法]。 另一种解决方案是在
    std::vector
    中存储
    lastpemplacedelemptr
    ,并从中删除一个适当的整数——但由于我们没有真正的
    MyType
    对象数组,这可能也是未定义的。事实上,一个例子声称如果我们有两个指针 对于比较相等的同一类型,其中一个可以安全地取消引用,而取消引用另一个仍然可以是未定义的

    那么,在C++17之前,有没有一种方法可以以可移植的方式实现std::vector? 或许STD::当你把新的东西放进去的时候,洗脸的确是C++的一个关键部分。 从C++98开始就没有了

    我知道这个问题表面上与其他许多问题相似,但据我所知,没有一个问题解释了如何合法地迭代由新布局构造的对象。事实上,这一切都有点令人困惑。例如,示例中的注释 表单
    std::对齐存储
    似乎表明在C++11和C++17之间已经有了一些变化,一个简单的
    在C++17之前,违反
    reinterpret_cast
    的别名是合法的[不需要
    std::launder
    ]。类似地,在
    std::malloc
    他们只需对
    std::malloc
    返回的指针(在
    static\u cast
    之后)执行一个指针算术,将其转换为正确的类型

    相比之下,根据对“何时放置新的和重新解释演员”的回答:

    自C++11以来,已经有一些重要的规则澄清 (特别是[基本生活])。但这些规则背后的意图并没有改变 变了


    评论不用于扩展讨论;这段对话已经结束。