如何对嵌套模板指针类型进行简洁初始化?
好的,咱们来一步步拆解这个问题,把这个复杂的指针嵌套类型的初始化搞明白。
首先得理清目标类型 A<A<A<int*>*>*>* 的结构:这是一个指向A<A<A<int*>*>*>对象的指针,从内到外每层A的模板参数都是「内层A类型的指针」——这和你之前用的A<A<A<int>>>(每层都是内层A的对象类型)有本质区别,所以初始化逻辑得适配指针参数的要求。
1. 兼容所有C++版本的完整写法
这种写法最直观,清晰对应每层的指针依赖:
A<A<A<int*>*>*>* a = new A<A<A<int*>*>*>{ new A<A<int*>*>{ new A<int*>{ new int(1) } } };
逐层解释:
- 最内层:
new int(1)创建一个int对象并返回int*,用来构造A<int*> - 中间层:
new A<int*>{...}创建A<int*>对象并返回A<int*>*,用来构造A<A<int*>*> - 外层:
new A<A<int*>*>{...}创建A<A<int*>*>对象并返回A<A<int*>*>*,用来构造A<A<A<int*>*>*> - 最终:
new A<A<A<int*>*>*>{...}创建最外层的A对象,返回的指针赋值给你的变量
2. C++17及以后的简化写法(利用类模板参数推导)
C++17引入了类模板参数推导(CTAD),new表达式可以自动推导A的模板参数,所以可以省略每层的模板参数声明,写法更简洁:
A<A<A<int*>*>*>* a = new A{ new A{ new A{ new int(1) } } };
关键注意事项:为什么不能用纯嵌套大括号?
你之前的A<A<A<int>>> a = {{{1}}}能用纯大括号,是因为每层A的构造函数接收的是对象类型,列表初始化可以直接构造内层对象并传递给外层。但现在每层A的构造函数需要的是指针类型:
- 直接写
{{{new int(1)}}}会构造一个临时的A<int*>对象,但临时对象的地址无法安全地作为指针参数传递(临时对象会立即销毁,导致指针悬空) - C++也不支持将
A<int*>对象隐式转换为A<int*>*指针,所以必须用new创建内层A对象,得到合法且持久的指针。
如果只是在局部作用域临时使用,也可以用栈对象的地址初始化,但一定要注意栈对象的生命周期(离开作用域后指针会悬空):
A<int*> a1{new int(1)}; A<A<int*>*> a2{&a1}; A<A<A<int*>*>*> a3{&a2}; A<A<A<int*>*>*>* a = &a3;
内容的提问来源于stack exchange,提问作者Alex Miller
相关产品推荐
相关产品推荐

