C++初始化vector时()与{}的区分规则及自定义类实现方法
C++ 初始化语法
()与{}的差异及自定义实现方案 一、编译器区分两种初始化的核心规则
C++11 引入的{}初始化被称为列表初始化,和传统()构造初始化的核心差异在于重载决议的优先级不同:
- 使用
{}初始化对象时,编译器会优先匹配参数为std::initializer_list<T>类型的构造函数:只要初始化列表中的所有元素都能隐式转换为T类型,就会优先调用该构造,只有没有匹配的std::initializer_list构造函数时,才会 fallback 到普通构造函数的重载决议逻辑。 - 使用
()初始化对象时,编译器完全不会考虑std::initializer_list类型的构造函数,只会按普通规则匹配对应的构造函数。
你给出的std::vector示例刚好符合这个规则:std::vector同时存在两个匹配的构造函数:
- 普通构造:
vector(size_t count),功能是创建包含count个默认初始化元素的容器 - 列表构造:
vector(std::initializer_list<int> init),功能是创建包含初始化列表中所有元素的容器
所以std::vector<int> v1(10)走普通构造,生成10个0元素的容器;std::vector<int> v2{10}优先匹配列表构造,把10作为列表的唯一元素,生成仅包含1个10的容器。
补充边界规则:如果
{}为空,编译器会优先调用默认构造函数,而非空的std::initializer_list构造。
二、自定义类实现两种初始化不同语义的方法
只要给自定义类同时定义对应功能的普通构造函数和接收std::initializer_list参数的列表构造函数即可,示例代码如下:
#include <iostream> #include <initializer_list> #include <vector> class MyIntContainer { private: std::vector<int> m_data; public: // 普通构造:参数为元素数量,生成对应数量的0元素 MyIntContainer(size_t elem_count): m_data(elem_count, 0) { std::cout << "调用普通构造:生成" << elem_count << "个0元素\n"; } // 列表构造:参数为初始化列表,将列表内元素存入容器 MyIntContainer(std::initializer_list<int> init_list): m_data(init_list) { std::cout << "调用列表构造:存入" << init_list.size() << "个元素\n"; } void print() const { for (int num : m_data) { std::cout << num << " "; } std::cout << "\n"; } }; int main() { MyIntContainer c1(3); // 走普通构造 c1.print(); // 输出:0 0 0 MyIntContainer c2{3}; // 走列表构造 c2.print(); // 输出:3 return 0; }
运行上述代码即可看到两种初始化方式对应不同的构造逻辑,实现了和std::vector一致的语义差异。
内容的提问来源于stack exchange,提问作者Pascal K
相关产品推荐
相关产品推荐

