将对象移动到 malloc 的内存中是否有效 C++?

Is moving an object into malloc'd memory valid C++?

如果内存是用 malloc 分配的(而不是 new)并且一个对象被移动到该内存中,那是有效的 C++ 吗? 假设我为 n 个类型为 T 的对象的数组分配内存,并且我有一个范围为 n 个类型为 T 的对象,我想将其移入该范围,这是否有效:

T* next = (T *)malloc(n*sizeof(T));
T* t = std::begin(my_range);
while (we still have more Ts) {
  *next = std::move(*t);   
  ++next;
  ++t;
}

这似乎可行,但我很好奇为什么会这样,因为我们从来没有在我们移动到的已分配内存中新建对象。

我的猜测是 放置新的 是正确的方法:

while (we still have more Ts) {
  new (next) T(*t);
  ++next;
  ++t;
}

但我想知道为什么第一个不正确,如果是这样,是不是运气好或者因为 T 恰好是 POD。

If memory is allocated with malloc (as opposed to new) and an object is moved into that memory, is that valid C++?

有可能;不一定。

如果我们考虑move-construction那么当然,你可以使用placement-new创建一个对象到内存中。有点像你的第二个例子——除了这个例子做了一个副本;除非迭代器很奇怪并且 returns 是右值。虽然,您提到的类型是 POD,在这种情况下,移动和复制之间没有区别。

如果我们考虑移动赋值,那么只有在之前已经创建了一个对象到该内存中的情况下,它才是明确定义的。在您的第一个示例中,没有创建任何对象,因此该行为在技术上是未定义的。

I'd like to know [...] if it just works by luck or because T happens to be a POD.

技术上 UB,但如果 T 是 POD,则很可能会起作用。这种通过赋值进行的初始化在 C 中有明确的定义(也是用该语言动态创建对象的唯一方法)。

如果赋值运算符不是平凡的,那么东西很可能会崩溃。


要将一系列对象移动到未初始化的内存中,您可能需要使用 std::uninitialized_move。无论类型的琐碎性如何,它都会被很好地定义,你甚至不必编写循环。