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()
时,将在先前分配的存储中创建一个对象。这可以很容易地实现与新的位置,这是完美的便携式。
但是现在,我们需要在不调用未定义行为的情况下访问已放置的元素
从
我知道有两种方法可以做到这一点
auto*elemPtr=new(bufferPtr)MyType()代码>
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以来,已经有一些重要的规则澄清
(特别是[基本生活])。但这些规则背后的意图并没有改变
变了
评论不用于扩展讨论;这段对话已经结束。