使用复制构造函数初始化 new[]

Initialize new[] using copy constructor

本文关键字:new 初始化 构造函数 复制      更新时间:2023-10-16

我相信这是一个简单的问题,可能不是一个简单的答案。

这是代码:

template<typename T>
T* copy(T* original, int size) {
T* result = new T[size];
// At this point the default constructor of all new T objects have been called.
for(int i = 0; i < size; ++i) {
// This will call the assignment operator= on all new T objects
result[i] = original[i];
}
return result;
}

问题:

有没有办法使用 T 的复制构造函数而不是使用默认构造函数后跟赋值运算符来初始化新分配的内存?

目的是使用 T 的复制构造函数将每个元素复制到新数组中的类似元素。

我想可能有一种方法可以通过使用malloc分配内存来做到这一点,然后为每个元素调用复制构造函数,但我不知道怎么做。

这是我想象中的示例解决方案。如果这是正确的,或者这是我们能得到的最好的,告诉我。或者提出更好的解决方案:

template<typename T>
T* copy(T* original, int size) {
T* result = malloc(sizeof(T)*size);
// At this point the default constructor of all new T objects have been called.
for(int i = 0; i < size; ++i) {
T t(original[i]);
memcpy(result+i*sizeof(T), &t, sizeof(T));
}
return result;
}

注意:为简单起见,使用原始指针。

注2:我不需要向量。此模式将用于复制更复杂对象的底层数据结构。

您必须通过任何其他方式分配内存,但请记住,size * sizeof(T)可能会溢出。std::allocator会处理这个问题。

使用std::uninitialized_copy/std::uninitialized_copy_n执行复制:

template<typename T>
T* copy(T* original, int size) {
std::allocator<T> alloc;
T* result = alloc.allocate(size);
try {
std::uninitialized_copy_n(original, size, result);
} catch (...) {
alloc.deallocate(result, size);
throw;
}
return result;
}

稍后您可以使用std::destroy/std::destroy_n销毁它们并释放内存:

template<typename T>
void destroy(T* ptr, int size)
{
std::destroy_n(ptr, size);
std::allocator<T>().deallocate(ptr, size);
}

除非您需要能够使用运算符delete[]删除它们,否则这应该有效 - 在这种情况下,没有解决方案。

如果要实现自定义容器,则可以像标准容器一样使用模板分配器:

template<typename T, typename Allocator = std::allocator<T>>
struct container
{
[[no_unique_address]] Allocator allocator;
...
};

对于new运算符,我不这么认为。

但是是的,有。它被称为std::vector

template<typename T>
std::vector<T> copy(T* original, int size) {
return std::vector<T>{original, original + size};
}

因为您不遵循 RAII 并使用拥有原始指针,所以您的代码不是没有内存泄漏的,所以不要这样做!正确使用C++。