You need to enable JavaScript to run this app. 如何改写C++ SortedList拷贝构造函数避免使用多个new运算符?
优惠活动
大模型
产品
解决方案
定价
更多

如何改写C++ SortedList拷贝构造函数避免使用多个new运算符?

问题根源分析

你尝试的T* new_element=& T(*(list.data[i]));写法本质是构造了一个临时T对象,临时对象的生命周期仅存在于当前表达式,表达式结束后立即销毁,此时你取到的地址是悬空指针,因此编译器会直接报taking address of temporary错误,该写法完全不可行。

另外你对“多余的new”的理解存在偏差:你当前的data成员是T**类型(存储T指针的数组),要做深拷贝的话,每个T对象本身就需要独立分配堆内存,你原来写的new T(*(list.data[i]))是实现深拷贝的必要操作,本身不是多余的。你认为的“不符合规范”,实际是裸指针手动管理内存带来的异常安全、内存泄漏风险,而非new操作本身多余。


解决方案

根据你的需求(不依赖T()默认构造、符合编码规范、减少不必要的内存分配),给出两种可选方案:

方案1:保留现有存储结构,用智能指针替代裸指针(改动最小)

将data的类型从裸二级指针改为std::unique_ptr<std::unique_ptr<T>[]>,利用RAII机制自动管理内存,不需要手动写delete,也完全避免内存泄漏风险,同时不需要修改核心逻辑:

template <class T>
SortedList<T>::SortedList(const SortedList<T>& list):
  data(std::make_unique<std::unique_ptr<T>[]>(list.max_size))
 ,size(list.size)
 ,max_size(list.max_size)
{
    for (int i = 0; i < size; i++)
    {
        data[i] = std::make_unique<T>(*list.data[i]);
    }
}

该方案依然保留每个T对象的独立内存分配,仅优化了内存管理方式,不需要依赖T的默认构造函数。

方案2:优化存储结构,去掉多余的指针间接层(推荐)

你当前用T**存储相当于多了一层不必要的指针跳转,改为直接存储T的一维数组即可,全程仅需要一次内存分配,完全去掉循环内的多个new操作。要避免调用T的默认构造,可以用std::allocator分配原始内存再手动构造对象:
首先修改类成员定义:

// 类内成员声明
T* data;
std::allocator<T> alloc;
size_t size;
size_t max_size;

拷贝构造实现:

template <class T>
SortedList<T>::SortedList(const SortedList<T>& list):
  data(alloc.allocate(list.max_size))
 ,size(list.size)
 ,max_size(list.max_size)
{
    for (int i = 0; i < size; i++)
    {
        std::construct_at(data + i, *list.data[i]);
    }
}

配套的析构函数实现:

template <class T>
SortedList<T>::~SortedList()
{
    for (int i = 0; i < size; i++)
    {
        std::destroy_at(data + i);
    }
    alloc.deallocate(data, max_size);
}

该方案全程仅调用一次内存分配,没有循环内的多余new操作,全程只调用T的拷贝构造函数,完全不依赖默认构造T(),性能和规范性都更好。

如果不想手动管理分配器,直接将data改为std::vector<T>即可,编译器自动生成的拷贝构造就能满足所有需求,不需要你手动写任何内存管理代码。


内容的提问来源于stack exchange,提问作者Raea6789

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 04:36:08