成员含默认初始化器时的聚合初始化:值数量不足的规则探究
聚合初始化中含默认成员初始化器时的剩余成员初始化规则
核心规则:当聚合类型带有默认成员初始化器,且聚合初始化提供的初始化值数量少于成员总数时,未被显式初始化的剩余成员会直接使用自身的默认成员初始化器完成初始化,而非执行值初始化。
规则对比与验证
先看learncpp文档中的描述:
初始化列表中缺少初始化器
若聚合类型被初始化但初始化值数量少于成员数量,则所有剩余成员将通过空初始化列表初始化。多数情况下,这会对这些成员执行值初始化。
该描述仅适用于无默认成员初始化器的聚合类型,通过示例代码和输出可以清晰看到两类场景的差异:
示例代码
#include <iostream> #include <type_traits> struct Employee_no_default_member_initializer { int id; int age; double wage; }; struct Employee_with_default_member_initializer { int id {1}; int age {20}; double wage {5.0}; }; template<typename T> class is_allowed_type:public std::false_type{}; template<> class is_allowed_type<Employee_with_default_member_initializer>:public std::true_type{}; template<> class is_allowed_type<Employee_no_default_member_initializer>:public std::true_type{}; template<typename T, typename std::enable_if<is_allowed_type<T>::value, void>::type* = nullptr> std::ostream& operator<<(std::ostream&os, const T& employee) { os << "id="<< employee.id << std::endl; os << "age="<< employee.age << std::endl; os << "wage="<< employee.wage << std::endl; return os; } template<typename T, typename std::enable_if<is_allowed_type<T>::value,void>::type* = nullptr> void foo() { T frank = { 3 }; // copy-list initialization using braced list T joe { 2, 28}; // list initialization using braced list (preferred) std::cout << frank << std::endl; std::cout << joe << std::endl; } int main() { std::cout << "#1" << std::endl; foo<Employee_with_default_member_initializer>(); std::cout << "#2" << std::endl; foo<Employee_no_default_member_initializer>(); return 0; }
输出结果
#1 id=3 age=20 wage=5 id=2 age=28 wage=5 #2 id=3 age=0 wage=0 id=2 age=28 wage=0
规则细节拆解
- 带默认成员初始化器的聚合:以
Employee_with_default_member_initializer为例,当用{3}初始化时,id被显式赋值为3,剩余的age、wage直接使用各自的默认初始化值(20、5.0);用{2,28}初始化时,id、age被显式赋值,wage依然沿用默认值5.0。 - 无默认成员初始化器的聚合:以
Employee_no_default_member_initializer为例,未被显式初始化的成员会执行值初始化——int类型被设为0,double类型被设为0.0,这与learncpp文档的描述完全一致。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

