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

时间:2020-05-16 10:04:44

标签: c++

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

代码如下:

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:我不需要向量。该模式将用于复制更复杂对象的基础数据结构。

2 个答案:

答案 0 :(得分:3)

您将不得不通过任何其他方式分配内存,但是请记住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;
    ...
};

答案 1 :(得分:0)

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

但是。称为std::vector

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

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