如果内存是用malloc
(而不是new
)分配的,并且一个对象被 move 到该内存中,那是有效的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;
}
这似乎可行,但我很好奇为什么会这样,因为我们从来没有在我们 move 到的已分配内存中新建对象。
我的猜测是placement new 是正确的做法:
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 来创建一个对象到内存中。有点像你的第二个例子——除了这个例子做了一个拷贝;除非迭代器很奇怪并返回一个右值。虽然,您提到的类型是 POD,但在这种情况下, move 和复制之间没有区别。
如果我们考虑 move 赋值,那么只有当之前在内存中创建了一个对象时,它才是明确定义的。在您的第一个示例中,没有创建任何对象,因此该行为在技术上是未定义的。
I'd like to know [...] if it just works by luck or because T happens to be a POD.
技术上是 UB,但如果 T
是 POD,则很可能会起作用。这种通过赋值进行的初始化在 C 中有明确的定义(也是用该语言动态创建对象的唯一方法)。
如果赋值运算符不是平凡的,那么东西很可能会崩溃。
要将一系列对象 move 到未初始化的内存中,您可能需要使用 std::uninitialized_move
。无论类型的琐碎性如何,它都会被很好地定义,您甚至不必编写循环。
关于c++ - 将对象 move 到 malloc 的内存中是否有效 C++?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54602385/