关于类的unique_ptr:成员变量头文件与构造函数初始化的差异
两种成员初始化方式的核心区别
首先明确:这个差异和unique_ptr无关——不管是用unique_ptr<A>创建A对象,还是直接在栈上声明A a,两种初始化B成员的逻辑区别完全一致,unique_ptr只是负责管理A对象的内存生命周期,不影响其内部成员的构造流程。
下面是两种情况的具体差异:
1. 对象构造的流程差异
情况1(类内初始化):
当A的对象被构造时,成员b会**直接调用B的带参构造函数B(int)**完成初始化,整个过程是一步到位的构造操作。对应的代码逻辑等价于在A的构造函数初始化列表中写:A::A() : b(B(1)) {}情况2(构造函数内赋值):
当A的对象被构造时,首先会调用B的**默认构造函数B()**创建成员b,然后在A的构造函数体内部,执行赋值操作b = B(1)——这会先创建一个临时的B对象(调用B(int)),再把临时对象的值赋值给已存在的b,整个过程是「默认构造 + 赋值」两步操作。
2. 对B类的构造函数要求不同
- 情况2必须要求B类提供可访问的默认构造函数,否则编译器会报错(因为要先默认构造
b); - 情况1只需要B类有可访问的
B(int)构造函数即可,完全不需要默认构造函数。
3. 效率与语义差异
- 情况1的效率更高:没有临时对象的创建和赋值操作,直接完成成员的构造;
- 情况2存在额外开销(即使编译器可能做优化消除临时对象,但从C++标准的语义上来说,是存在「默认构造→临时对象构造→赋值」这几步的);
- 如果
b是const B类型,情况2的赋值操作会直接编译失败(常量对象不能被赋值),但情况1可以正常完成初始化(因为是在构造阶段给常量赋值)。
内容的提问来源于stack exchange,提问作者Baptiste Girard
相关产品推荐
相关产品推荐

