C++如何通过构造函数成员初始化列表初始化C风格char和int数组
警告触发原因与单int无警告的差异
- Clang-Tidy的该警告核心逻辑是检测类的聚合类型成员是否在构造函数的初始化列表中完成了初始化。你在构造函数体内对
p、str的操作属于赋值,在进入构造函数体之前,这两个数组已经完成了默认初始化:内置类型数组的默认初始化不会自动填充值,会处于不确定值状态。Clang-Tidy不会校验数组所有元素是否在构造函数体内被全量赋值,因此只要数组未在初始化列表显式初始化就会触发警告。 - 单个
int类型成员不会触发警告的原因是:对于标量内置类型,Clang-Tidy会执行数据流分析,如果能确认构造函数所有执行路径都对该标量完成了赋值,就会判定不存在未初始化使用的风险,因此不会告警。
初始化列表初始化原生数组的方案
你可以直接在初始化列表中对数组做零初始化,既符合Clang-Tidy的规则,也不影响后续赋值逻辑,实现简单且兼容性好:
#include <iostream> #include <cstring> class A { private: int p[5]; char str[20]; public: A(int *q, const char *s): p{}, str{} // 初始化列表完成数组零初始化 { for(int i=0; i<=4; i++) { p[i] = q[i]; } // 用strncpy替代strcpy避免字符串溢出风险 strncpy(str, s, sizeof(str)-1); str[sizeof(str)-1] = '\0'; // 强制补字符串结束符 } }; int main() { int r[5]={2, 3, 5, 7, 11}; char ch[]="bonaparte"; A a1(r, ch); return 0; }
如果你希望在初始化列表阶段就完成数组元素的拷贝而非零初始化后再赋值,可以借助C++14及以上的std::index_sequence实现索引展开:
#include <iostream> #include <cstring> #include <utility> class A { private: int p[5]; char str[20]; // 辅助构造函数,用索引序列展开完成数组元素初始化 template<std::size_t... I> A(int *q, const char* s, std::index_sequence<I...>) : p{q[I]...}, str{} { strncpy(str, s, sizeof(str)-1); str[sizeof(str)-1] = '\0'; } public: A(int *q, const char* s): A(q, s, std::make_index_sequence<5>{}) {} }; int main() { int r[5]={2, 3, 5, 7, 11}; char ch[]="bonaparte"; A a1(r, ch); return 0; }
内容的提问来源于stack exchange,提问作者Abhishek Mane
相关产品推荐
相关产品推荐

