C++map和vector在没赋值情况下的默认值

本文探讨了C++中map和vector使用operator[]时的越界行为,并通过实例展示了当查询的键不存在或访问的索引超出范围时,两者如何提供默认值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

map和vector都可以用operator[]进行访问,map是用[]中的数据作为key进行查询,而vector是用[]中的数作为下标进行访问。

如果在用operator[]进行访问的时候出现了越界情况,即map没有这个键值对,或vector的大小小于下标数值,会发生什么情况?

struct node{int a{5};};
int main() {
    map<string,node> m1;
    cout<<m1["s"].a<<endl;
    map<string,int> m2;
    cout<<m2["s"]<<endl;
    vector<node> v1(3);//需要指定vector大小,否则不能在没有push_back的情况用下标访问 
    cout<<v1[0].a<<endl;
    vector<int> v2(3);
    cout<<v2[0];
}

结果:

5
0
5
0

由上面示例程序可看出map和vector在越界情况都会给出此类型的默认值,如果是基本类型,则返回零值;如果是struct或class,如果里面的变量定义了默认值,则返回定义的默认值,如果没有,返回零值。

<think>我们在C++结构体或类的构造函数中使用初始化列表来初始化成员变量,包括vectormap等容器成员。 初始化列表位于构造函数参数列表之后,以冒号开始,用逗号分隔各个成员的初始化式。 对于vectormap,我们可以使用多种方式在初始化列表中初始化,例如: 1. 使用默认初始化(即空容器) 2. 使用初始化列表(花括号)进行初始化 3. 使用其他构造函数(比如指定大小初始值) 注意:在C++11及以后,我们可以使用花括号初始化(即std::initializer_list)来初始化容器。 下面是一个示例结构体,它包含一个vector一个map成员,并在构造函数中使用初始化列表进行初始化。 引用说明: [^1]: 关于std::initializer_list的使用,我们可以为类定义一个接受std::initializer_list的构造函数,从而支持列表初始化。 [^2]: 在C++中,如果定义了任何拷贝控制成员(拷贝构造函数、拷贝赋值运算符、析构函数等),则应该考虑所有五个特殊成员函数(新增了移动构造函数移动赋值运算符),即“五法则”。 [^3]: 构造函数的explicit关键字可以防止隐式转换。 [^4]: 参考文献中提到了C++ Primer中的相关内容,其中详细介绍了初始化列表容器初始化。 示例代码: */ ```cpp #include <vector> #include <map> #include <string> struct MyStruct { std::vector<int> vec; std::map<std::string, int> myMap; // 构造函数1:使用初始化列表进行默认初始化(空vectormap) MyStruct() : vec(), myMap() {} // 构造函数2:使用给定的初始化列表初始化vectormap MyStruct(std::initializer_list<int> vec_init, std::initializer_list<std::pair<const std::string, int>> map_init) : vec(vec_init), myMap(map_init) {} // 构造函数3:使用vector的构造函数map的构造函数进行初始化 // 例如:指定vector的大小初始值,以及用另一个map的范围初始化 MyStruct(int vec_size, int vec_value, const std::map<std::string, int>& another_map) : vec(vec_size, vec_value), myMap(another_map) {} }; int main() { // 使用默认构造函数 MyStruct s1; // vecmap都是空的 // 使用初始化列表构造函数 MyStruct s2({1, 2, 3}, {{"one", 1}, {"two", 2}}); // s2.vec = {1,2,3}; s2.myMap = {"one":1, "two":2} // 使用第三个构造函数 std::map<std::string, int> m = {{"apple", 5}, {"banana", 3}}; MyStruct s3(5, 10, m); // s3.vec = 5个元素,每个都是10;s3.myMap是m的拷贝 return 0; } ``` /* 说明: 1. 在第一个构造函数中,我们使用空的初始化列表,即调用vectormap的默认构造函数,创建空容器。 2. 第二个构造函数使用了std::initializer_list,这样我们可以在构造结构体时直接使用花括号传入vectormap的初始值。 注意:map的初始化列表中的元素类型是std::pair<const Key, T>,这里我们使用了const std::string作为键。 3. 第三个构造函数展示了如何使用vector的构造函数(指定大小初始值)map的拷贝构造函数进行初始化。 注意事项: - 在初始化列表中,成员初始化的顺序应该与成员在类中声明的顺序一致,否则可能导致混淆(尽管编译器可能不会报错,但依赖初始化顺序的代码可能难以维护)。 - 对于map的初始化,如果使用初始化列表,注意键必须是const的(在std::pair中,键是const的,因为map中的键不可修改)。 - 如果结构体中有多个构造函数,注意避免歧义。 另外,在C++11及以后,我们还可以使用非静态数据成员初始化(即在声明成员时直接初始化),例如: struct MyStruct { std::vector<int> vec = {1,2,3}; // 声明时初始化 std::map<std::string, int> myMap = {{"a",1},{"b",2}}; }; 这样,如果有在构造函数初始化列表中显式初始化,它们就会使用这些默认值。 但是,如果同时在初始化列表中初始化,则初始化列表中的值会覆盖声明时的初始值。 所以,根据你的需求,可以选择在声明时初始化,或者在构造函数初始化列表中初始化。 相关问题: 1. 在C++结构体中,如何为容器成员(如vectormap)提供默认值? 2. 使用初始化列表初始化map时需要注意什么? 3. 在构造函数初始化列表中初始化成员的顺序有什么要求? 4. 如何避免多个构造函数导致的歧义? */</think>在C++结构体的构造函数初始化列表中初始化`vector``map`成员时,需遵循容器初始化的语法规则。以下是具体方法示例: --- ### **初始化方法** 1. **默认初始化**:创建空容器 2. **列表初始化**:直接传递初始元素(C++11起支持) 3. **拷贝/移动初始化**:从其他容器复制 4. **指定大小值**:仅适用于`vector` --- ### **示例代码** ```cpp #include <vector> #include <map> #include <string> struct Data { std::vector<int> vec; std::map<std::string, int> myMap; // 方法1:默认初始化(空容器) Data() : vec(), myMap() {} // 方法2:列表初始化(直接提供元素) Data(std::initializer_list<int> v, std::initializer_list<std::pair<const std::string, int>> m) : vec(v), myMap(m) {} // 方法3:指定vector大小初始值 + map拷贝初始化 Data(size_t size, int vec_val, const std::map<std::string, int>& m) : vec(size, vec_val), myMap(m) {} }; int main() { // 使用列表初始化 Data d1({1, 2, 3}, {{"a", 10}, {"b", 20}}); // 使用拷贝初始化 std::map<std::string, int> m = {{"x", 100}, {"y", 200}}; Data d2(5, 0, m); // vector: 5个0, map拷贝m } ``` --- ### **关键注意事项** 1. **初始化顺序** 成员初始化顺序需与声明顺序一致(此处`vec`先于`myMap`)[^2]。 2. **`map`的键类型** 列表初始化时,`std::pair`的键必须是`const`类型(如`std::pair<const std::string, int>`)[^1]。 3. **显式构造函数** 若构造函数可能引起隐式转换,需用`explicit`关键字(如单参数构造函数)[^3]。 4. **五法则(Rule of Five)** 若自定义析构函数,需同时处理拷贝/移动构造赋值运算符[^2]。 --- ### **常见问题解决方案** | 问题类型 | 解决方法 | |------------------|--------------------------------------------------------------------------| | 初始化空容器 | `: vec(), myMap()` | | 直接初始化元素 | 使用`std::initializer_list`(如`vec({1,2,3})`)[^1] | | 初始化大型容器 | 在构造函数体内用循环填充(避免初始化列表过长) | | 动态键值对 | 构造函数体内用`myMap.insert(...)`动态添加 | > 提示:C++11起支持**类内成员初始化**,可直接声明时赋值: > ```cpp > struct Data { > std::vector<int> vec = {1, 2, 3}; > std::map<std::string, int> myMap = {{"default", 0}}; > }; > ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值