将对象移动到 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
。无论类型的琐碎性如何,它都会被很好地定义,你甚至不必编写循环。
如果内存是用 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
。无论类型的琐碎性如何,它都会被很好地定义,你甚至不必编写循环。