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

在成员初始化列表中初始化智能指针数据成员的弊端是什么?

成员初始化列表初始化智能指针的弊端分析

问题描述

假设存在类B,它包含一个指向类A对象的智能指针成员。已知在成员初始化列表中初始化智能指针比在构造函数体内调用reset赋值更快,但不清楚这种初始化方式的弊端。请问在成员初始化列表中初始化该智能指针成员有什么缺点?

测试代码

#include <chrono>
#include <iostream>
#include <memory>

struct A {
};

struct B1 {
    B1(): a(new A) {}
    std::unique_ptr<A> a;
};

struct B2 {
    B2() {
        a.reset(new A);
    }
    std::unique_ptr<A> a;
};

int main() {
    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    for(auto i=0; i < 100000; ++i) {
        B1 b;
        // B2 b;
    }
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    std::cout << (end - begin).count() << std::endl;
}

测试结果

B1(初始化列表初始化):8054043
B2(构造函数体内reset赋值):8894576

弊端分析

虽然成员初始化列表初始化智能指针的性能更优,但存在以下明显缺点:

  • 复杂场景下的异常安全风险:当初始化逻辑涉及多个可能抛出异常的操作时,裸指针的中间状态可能导致内存泄漏。例如,若在初始化列表中同时执行多个new操作,或把new的结果作为参数传递给其他可能抛出异常的函数,由于C++中函数参数的求值顺序不确定,可能出现new分配内存后,智能指针还未完成构造就抛出异常的情况,此时已分配的内存无法被智能指针接管,最终泄漏。

  • 不符合现代C++最佳实践:C++14及以后标准推荐使用std::make_unique创建unique_ptr,该函数在智能指针内部完成内存分配与对象构造,完全避免了裸指针的暴露,从根源上杜绝了上述泄漏风险。而直接用new初始化智能指针,本质上仍依赖裸指针,违背了智能指针设计的初衷。

  • 代码可读性与维护性不足:new的写法不如make_unique直观,其他开发者需要额外关注裸指针的生命周期;而make_unique明确表达了“创建一个受智能指针管理的对象”的意图,代码更清晰,后续维护时出错概率更低。

需要注意的是,在你提供的简单测试场景中,直接用new初始化不会出现泄漏问题,但一旦代码复杂度提升,潜在风险会显著增加。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:55:18