C++11/14介绍(四)——新增容器(二)

无序容器

传统 C++ 中的有序容器 std::map/std::set,这些容器内部通过红黑树进行实现,插入和搜索的平均复杂度均为 O(log(size))。在插入元素时候,会根据 < 操作符比较元素大小并判断元素是否相同,并选择合适的位置插入到容器中。当对这个容器中的元素进行遍历时,输出结果会按照 < 操作符的顺序来逐个遍历。

而无序容器中的元素是不进行排序的,内部通过 Hash 表实现,插入和搜索元素的平均复杂度为 O(constant),在不关心容器内部元素顺序时,能够获得显著的性能提升。

C++11 引入了两组无序容器:std::unordered_map/std::unordered_multimap 和 std::unordered_set/std::unordered_multiset。

它们的用法和原有的 std::map/std::multimap/std::set/set::multiset 基本类似,这里比较一下std::map和std::multimap:

#include <iostream>
#include <string>
#include <unordered_map>
#include <map>

int main() {
    // 两组结构按同样的顺序初始化
    std::unordered_map<int, std::string> u = {
        {1, "1"},
        {3, "3"},
        {2, "2"}
    };
    std::map<int, std::string> v = {
        {1, "1"},
        {3, "3"},
        {2, "2"}
    };

    // 分别对两种容器进行遍历
    std::cout << "std::unordered_map" << std::endl;
    for( const
C++11C++14C++17 是现代 C++ 发展中的三个重要标准版本,它们引入了许多新特性,极大增强了语言的表达能力和性能优化能力。这些特性的掌握对于通过高级 C++ 技术面试至关重要。 ### 自动类型推导(`auto` 与 `decltype`) C++11 引入了 `auto` 关键字,允许编译器自动推断变量的类型,简化了复杂类型的声明过程。例如: ```cpp auto i = 42; // i 的类型被推断为 int auto& j = i; // j 是 i 的引用 ``` `decltype` 则用于获取表达式的类型,常用于模板元编程中保持类型一致性[^3]。 ### Lambda 表达式 C++11 提供了对匿名函数的支持,称为 lambda 表达式。它使得编写内联函数变得简单,并且可以捕获上下文中的变量。例如: ```cpp #include <vector> #include <algorithm> std::vector<int> v = {1, 2, 3, 4, 5}; int x = 3; v.erase(std::remove_if(v.begin(), v.end(), [x](int n) { return n < x; }), v.end()); ``` 此例中,lambda 函数 `[x](int n) { return n < x; }` 捕获了变量 `x` 并用于判断是否移除元素[^3]。 ### 移动语义与右值引用 C++11 引入了右值引用 (`T&&`) 和移动构造函数/赋值运算符的概念,从而实现了高效的资源转移机制。这在处理大型对象(如容器)时特别有用,避免不必要的深拷贝操作。例如: ```cpp class MyClass { public: MyClass(MyClass&& other) noexcept : data(other.data) { other.data = nullptr; // 将原对象的资源置空 } private: int* data; }; ``` 上述代码展示了如何定义一个移动构造函数来实现资源的有效转移[^2]。 ### 智能指针 为了更好地管理动态分配的内存并防止内存泄漏,C++11 标准化了几种智能指针类型,包括 `std::unique_ptr`、`std::shared_ptr` 和 `std::weak_ptr`。其中,`std::unique_ptr` 确保了单一所有权模型,而 `std::shared_ptr` 使用引用计数来跟踪有多少个智能指针共享同一个资源。使用示例如下: ```cpp #include <memory> std::unique_ptr<int> uptr(new int(10)); // 创建 unique_ptr std::shared_ptr<int> sptr = std::make_shared<int>(20); // 创建 shared_ptr ``` 此外,还可以为 `std::shared_ptr` 提供自定义删除器以适应特定需求[^3]。 ### constexpr 与常量表达式 从 C++11 开始,`constexpr` 被用来指定某个变量或函数可以在编译时期求值,这对于提高程序运行效率非常有帮助。例如: ```cpp constexpr int square(int x) { return x * x; } int arr[square(5)]; // 编译时常量表达式 ``` 这里,`square(5)` 在编译期间就被计算成了 25,因此可以直接作为数组大小使用。 ### 初始化列表与统一初始化语法 C++11 还引入了一种新的初始化方式——使用大括号 `{}` 进行初始化,这种做法被称为统一初始化或者列表初始化。它可以应用于几乎所有数据类型的初始化场景,并且有助于避免最令人困惑的解析问题(most vexing parse)。例如: ```cpp std::vector<int> vec{1, 2, 3}; // 列表初始化 vector MyClass obj{}; // 默认初始化 ``` 这种方式不仅简洁明了,而且能够有效减少错误的发生[^3]。 ### 可选类型(`std::optional`) 尽管 `std::optional` 是在 C++17 中才被正式纳入标准库的,但它已经成为处理可能不存在值的情况下的首选方案之一。它提供了一种安全的方式来表示“无值”状态,替代传统的使用空指针或者特殊标志位的做法。用法如下: ```cpp #include <optional> std::optional<int> maybeInt = getSomeValue(); // 假设该函数返回一个可选整数 if (maybeInt) { std::cout << "Got value: " << *maybeInt << std::endl; } else { std::cout << "No value present." << std::endl; } ``` 以上仅是 C++11/14/17 新增功能的一部分概述;深入理解和实践这些特性对于准备技术面试来说是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值