C++11中如何正确使用花括号初始化器?嵌套结构体初始化报错
C++11嵌套结构体与std::vector初始化错误解决
问题场景
我在项目中定义了3个嵌套结构体,想要创建供多个函数使用的默认配置,尝试了以下代码:
struct xBitValue { size_t depth=0; uint64_t key=1; //allow comparison bool operator==(const xBitValue& b) const { return ((depth==b.depth) && (key==b.key)); } bool operator!=(const xBitValue& b) const { return ((depth!=b.depth) || (key!=b.key)); } }; struct stringHeaderOption { xBitValue header; size_t encoder=0; }; struct stringHeaderOptions { size_t xBitLength; std::vector<stringHeaderOption> options; }; const stringHeaderOptions defaultHeaderOptions={2,{ {{0,1},0}, {{0,2},1}, {{0,3},2}, {{1,1},3} }};
编译时出现错误:无法将{{{0, 1}, 0}, {{0, 2}, 1}, {{0, 3}, 2}, {{1, 1}, 3}}从<brace-enclosed initializer list>转换为std::vector<stringHeaderOption>,错误指向最后一个},使用的是C++11标准。
错误原因
在C11标准中,聚合体不允许包含默认成员初始化器(即成员声明时直接赋值的写法,比如size_t depth=0)。你的xBitValue和stringHeaderOption结构体因为使用了默认成员初始化,不再属于C11的聚合体范畴,无法通过{...}这种聚合初始化的方式直接构造对象。而你在初始化std::vector<stringHeaderOption>时,尝试用嵌套大括号构造非聚合体对象,这就触发了编译错误。
解决方案
方案1:移除默认成员初始化,添加构造函数(兼容C++11)
修改结构体定义,为每个结构体添加带默认参数的构造函数,替代原来的默认成员初始化逻辑,之后通过显式构造调用完成初始化:
struct xBitValue { size_t depth; uint64_t key; // 带默认参数的构造函数,替代默认成员初始化 xBitValue(size_t d = 0, uint64_t k = 1) : depth(d), key(k) {} bool operator==(const xBitValue& b) const { return ((depth==b.depth) && (key==b.key)); } bool operator!=(const xBitValue& b) const { return ((depth!=b.depth) || (key!=b.key)); } }; struct stringHeaderOption { xBitValue header; size_t encoder; // 构造函数,encoder带默认值 stringHeaderOption(xBitValue h, size_t e = 0) : header(h), encoder(e) {} }; struct stringHeaderOptions { size_t xBitLength; std::vector<stringHeaderOption> options; // 构造函数 stringHeaderOptions(size_t len, std::vector<stringHeaderOption> opts) : xBitLength(len), options(std::move(opts)) {} }; // 显式调用构造函数完成默认配置初始化 const stringHeaderOptions defaultHeaderOptions(2, { stringHeaderOption(xBitValue(0,1), 0), stringHeaderOption(xBitValue(0,2), 1), stringHeaderOption(xBitValue(0,3), 2), stringHeaderOption(xBitValue(1,1), 3) });
方案2:升级编译标准到C++14及以上
C++14放宽了聚合体的定义,允许聚合体包含默认成员初始化器。只需将编译选项改为-std=c++14(或更高版本如-std=c++17),你原来的代码就能直接编译通过,无需修改结构体和初始化逻辑。
内容的提问来源于stack exchange,提问作者Matthew Cornelisse
相关产品推荐
相关产品推荐

