You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用unique_ptr替换new/delete时复合类型初始化报错的解决方法

问题分析与解决

错误原因

问题核心在于列表初始化和构造函数调用初始化的语法差异:

  • 原new/delete版本中,new T{std::forward<Args>(args)...}使用花括号的列表初始化,对于Point这类聚合类型(无用户定义构造函数的类),可以直接通过列表为成员变量x和y赋值。
  • 而std::make_unique的内部实现是new T(std::forward<Args>(args)...),即圆括号的构造函数调用初始化。由于Point没有接收两个int参数的构造函数,编译器会尝试把1,2解析为逗号表达式(最终结果为2),进而寻找Point(int)构造函数,自然找不到匹配项,因此报错。

解决方案

方案1:修改dynamic构造逻辑,兼容列表初始化

绕开make_unique的限制,直接构造unique_ptr时用花括号初始化T,既保留自动内存管理,又延续原版本的聚合类型支持:

template <typename T>
struct dynamic {
    explicit dynamic(const T& value = T{}) 
        : ptr(std::unique_ptr<T>(new T{value})) {}

    template <typename... Args>
    dynamic(Args&&... args) 
        : ptr(std::unique_ptr<T>(new T{std::forward<Args>(args)...})) {}

    operator T&() { return *ptr; }
    T* operator->() { return ptr.get(); }

    std::unique_ptr<T> ptr;
};

方案2:给聚合类型添加构造函数

如果允许修改Point的定义,新增对应构造函数,让make_unique能正常调用构造逻辑:

struct Point {
    int x;
    int y;
    Point(int x_, int y_) : x(x_), y(y_) {} // 新增构造函数
};

此时std::make_unique<Point>(1,2)会直接调用该构造函数,无需依赖列表初始化。

方案3:C++20+直接兼容

C20起通过P0960提案支持聚合类型的括号初始化,若你的编译器开启C20及以上标准,原代码可直接编译通过,无需修改。

修改后完整代码(方案1示例)

#include <iostream>
#include <memory>

template <typename T>
struct dynamic {
    explicit dynamic(const T& value = T{}) 
        : ptr(std::unique_ptr<T>(new T{value})) {}

    template <typename... Args>
    dynamic(Args&&... args) 
        : ptr(std::unique_ptr<T>(new T{std::forward<Args>(args)...})) {}

    operator T&() { return *ptr; }
    T* operator->() {
        return ptr.get();
    }

    std::unique_ptr<T> ptr;
};

struct Point {
    int x;
    int y;
};

int main() {
    dynamic<int> i = 123;
    std::cout << i << '\n';

    dynamic<Point> p{1, 2};
    std::cout << static_cast<Point&>(p).x << ' ' << p->y << '\n';

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:47:42