#include <iostream>
#include <type_traits>
using namespace std;
// Non-trivially-copyable type.
struct NTC
{
int x;
NTC(int mX) : x(mX) { }
~NTC() { cout << "boop." << x << endl; }
};
int main()
{
using AS = aligned_storage_t<sizeof(NTC), alignof(NTC)>;
// Create two `std::aligned_storage` instances
// and "fill" them with two "placement-new-constructed"
// `NTC` instances.
AS as1, as2;
new (&as1) NTC{2};
new (&as2) NTC{5};
// Swap the `aligned_storages`, not their contents.
std::swap(as1, as2);
// Explicitly call `~NTC()` on the contents of the
// aligned storage instances.
NTC& in1{*static_cast<NTC*>(static_cast<void*>(&as1))};
NTC& in2{*static_cast<NTC*>(static_cast<void*>(&as2))};
in1.~NTC();
in2.~NTC();
return 0;
}
以上代码是否未定义行为?
这就是我认为发生的事情:
NTC
是一种非平凡的可复制类型。 NTC
个对象的内存位置(std::aligned_storage
)。NTC
实例直接构建到内存位置。std::aligned_storage
instances are PODTypes。
这意味着该类型与C编程语言中使用的类型兼容,可以使用C库函数进行操作:它可以使用std :: malloc创建,可以使用std :: memmove等进行复制,并且可以用二进制形式直接与C库交换。
NTC
对象的析构函数/复制构造函数。我的任何一点不正确?如果确实发生未定义的行为,程序的哪个部分会发生?为什么?
新可能正确/不正确的信息(gathered from a deleted answer):
std::aligned_storage
几乎只是C风格数组的typedef。std::swap
has an overload for C-style arrays since C++11。std::swap_ranges
,它交换数组中的每个元素。std::aligned_storage
实例应该逐个元素地交换它们的内容。我是否在这些新假设中犯了错误?
答案 0 :(得分:5)
在放入非平凡可复制类型之后直接访问缓冲区的字节是一个非常糟糕的主意,但尚未定义。
在作为NTC
交换后尝试访问缓冲区违反了别名规则,[basic.lval] p10:
如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
(10.1) - 对象的动态类型,
[...]
隐含通过memcpy
或等效类型复制一个简单的可复制类型来保留动态类型。对于非平凡的可复制类型没有这样的含义,因此在交换之后,您不再有任何NTC
个对象可供访问。