STL --- 八. STL的高级特性和应用实例

目录

一、STL 的高级特性

1、分配器(Allocators)

2、数值算法(Numeric Algorithms)

3、本地化(Localization)

4、多线程(Multithreading)

二、STL 应用实例

1、STL 在数据结构中的应用

2、STL 在算法设计中的应用

3、STL 在实际工程中的应用


一、STL 的高级特性

1、分配器(Allocators)

        STL(Standard Template Library)的分配器是一个用于动态分配内存的对象。它是一个模板类,可以为STL容器的元素分配内存。STL分配器提供了一种可移植的方式来管理内存,它可以根据需要自动调整内存大小,并提供了一些特殊的内存分配策略,如内存池和堆栈分配等。STL分配器使用C++的new和delete操作符来分配和释放内存,可以在不同的平台和编译器下使用。它是STL的重要组成部分,对于实现高效、可靠和可移植的STL程序非常重要。

使用 STL 分配器的示例代码:

#include <iostream>
#include <vector>
#include <memory>

int main() {
    // 使用 STL 分配器分配内存
    std::allocator<int> alloc;
    int* p = alloc.allocate(10);
    for (int i = 0; i < 10; ++i) {
        p[i] = i;
    }

    // 使用 STL 容器存储元素
    std::vector<int, std::allocator<int>> vec(alloc);
    for (int i = 0; i < 10; ++i) {
        vec.push_back(i);
    }

    // 使用 STL 分配器释放内存
    alloc.deallocate(p, 10);

    return 0;
}

在这个示例中,我们首先创建了一个 std::allocator<int> 类型的分配器 alloc,然后使用 alloc.allocate(10) 分配了 10 个 int 类型的内存空间,将其赋值给指针 p,并对这些内存空间进行了初始化。

接着,我们创建了一个 std::vector<int, std::allocator<int>> 类型的容器 vec,并将 alloc 作为其分配器。然后使用 vec.push_back(i) 将 0 到 9 这 10 个整数添加到容器中。

最后,我们使用 alloc.deallocate(p, 10) 将之前分配的内存空间释放掉。

需要注意的是,在使用 STL 容器时,如果没有指定分配器类型,则会使用默认的分配器,即 std::allocator。如果需要使用其他类型的分配器,需要将其作为容器的第二个模板参数传入。

2、数值算法(Numeric Algorithms)

STL 数值算法(Numeric Algorithms)是一组用于数值计算和处理的算法,包括数值操作、数值统计、数值转换等功能。这些算法是在 <numeric> 头文件中定义的。

常用的 STL 数值算法包括:

#include <numeric>
1. accumulate:计算一个序列中所有元素的和。
2. inner_product:计算两个序列的点积。
3. partial_sum:计算一个序列的部分和。
4. adjacent_difference:计算一个序列相邻元素的差值。
5. iota:生成一个序列,其中每个元素的值依次递增。
6. gcd、lcm:计算两个整数的最大公约数和最小公倍数。
7. power:计算一个数的幂次方。
8. sqrt、cbrt:计算一个数的平方根和立方根。
9. abs、fabs、absdiff:计算一个数的绝对值或两个数的差的绝对值。
10. round、floor、ceil、trunc:对一个数进行舍入操作。

STL 数值算法可以简化数值计算和处理的代码编写,提高代码的可读性和可维护性。

数值算法实例:

#include <iostream>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 1、accumulate函数:计算容器中所有元素的和
    int sum = std::accumulate(v.begin(), v.end(), 0);
    std::cout << "The sum is " << sum << std::endl; // 15

    
    // 2、inner_product函数:计算两个容器的内积
    std::vector<int> v1 = {1, 2, 3};
    std::vector<int> v2 = {4, 5, 6};
    int result = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0);
    std::cout << "The inner product is " << result << std::endl; //32

    
    // 3、adjacent_difference函数:计算容器相邻元素之间的差值
    std::vector<int> v = {1, 3, 5, 7, 9};
    std::vector<int> result(v.size());
    std::adjacent_difference(v.begin(), v.end(), result.begin());
    std::cout << "The adjacent difference is ";
    for (auto val : result) {
        std::cout << val << " ";
    }
    // The adjacent difference is 1 2 2 2 2
    // 注意,第一个元素是原容器中的第一个元素,因为它没有前一个元素可以计算差值。
    std::cout << std::endl;

    
    // 4、partial_sum函数:计算容器前缀和
    std::vector<int> v = {1, 2, 3, 4, 5};
    std::vector<int> result(v.size());
    std::partial_sum(v.begin(), v.end(), result.begin());
    std::cout << "The partial sum is ";
    for (auto val : result) {
        std::cout << val << " ";
    }
    // The partial sum is 1 3 6 10 15
    std::cout << std::endl;

}

3、本地化(Localization)

STL本地化(Localization)是指将STL库中的一些函数和类适应不同的语言和文化环境,以便更好地适应不同地区的用户需求。本地化主要包括以下方面:

(1)日期和时间格式:不同国家和地区对日期和时间的格式要求不同。STL库中的一些函数和类需要根据不同的文化环境来设置日期和时间格式。

(2)字符编码:不同国家和地区使用不同的字符编码,如中文常用的GB2312、GBK、UTF-8等。STL库中的一些函数和类需要根据不同的字符编码来处理字符串。

(3)数字格式:不同国家和地区对数字的格式要求不同,如小数点的位置、千位分隔符的使用等。STL库中的一些函数和类需要根据不同的文化环境来处理数字格式。

(4)货币和货币符号:不同国家和地区的货币符号不同,如美元符号"$"、欧元符号"€"等。STL库中的一些函数和类需要根据不同的文化环境来处理货币和货币符号。

(5)字符串排序:不同语言和文化环境对字符串的排序方式不同,如英语按字母顺序排序,中文按拼音排序。STL库中的一些函数和类需要根据不同的文化环境来处理字符串排序。

通过本地化,STL库可以更好地适应不同地区的用户需求,提高程序的可用性和用户体验。

本地化实例:可以使用 C++11 引入的 std::wstring_convert 类和 std::locale 类来实现本地化。

#include <iostream>
#include <vector>
#include <string>
#include <locale>
#include <codecvt>

int main()
{
    // 创建一个 vector 容器,存储一些字符串
    std::vector<std::string> strings = {"Hello", "world", "!"};

    // 创建一个本地化对象,指定本地化为中文
    std::locale loc("zh_CN.UTF-8");

    // 创建一个宽字符串转换器,用于将 std::string 转换为 std::wstring
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;

    // 遍历 vector 容器中的每一个字符串,并进行本地化处理
    for (const auto& str : strings)
    {
        // 将 std::string 转换为 std::wstring
        std::wstring wstr = converter.from_bytes(str);

        // 在本地化环境下输出宽字符串
        std::wcout.imbue(loc);
        std::wcout << wstr << std::endl;
    }

    return 0;
}

在上面的示例中,我们首先创建了一个 vector 容器,并存储了一些字符串。然后,我们创建了一个本地化对象,并指定本地化为中文。接着,我们创建了一个宽字符串转换器,用于将 std::string 转换为 std::wstring。最后,我们遍历 vector 容器中的每一个字符串,并进行本地化处理,将字符串转换为宽字符串,并在本地化环境下输出宽字符串。

4、多线程(Multithreading)

STL(Standard Template Library)是C++的一个标准库,其中包含了很多数据结构和算法。

STL多线程是使用STL库来实现多线程编程的一种方法。

STL多线程提供了一些类和函数来支持多线程编程,包括:

(1)std::thread:用于创建一个新的线程。

(2)std::mutex:用于实现互斥锁,保护共享资源。

(3)std::condition_variable:用于实现条件变量,允许线程之间等待某个条件的发生。

(4)std::future和std::promise:用于实现异步操作,允许一个线程在另一个线程完成某个任务后获取结果。

使用STL多线程编程可以提高程序的并发性和效率,但也需要注意一些问题,比如线程安全、死锁和资源竞争等。因此,在使用STL多线程时需要仔细考虑线程之间的交互和同步问题,以避免出现异常情况。

多线程实例:

#include <iostream>
#include <thread>
#include <vector>
#include <algorithm>

void print_num(int num) {
    std::cout << num << std::endl;
}

int main() {
    std::vector<int> nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 创建 5 个线程,每个线程输出一组数字
    std::vector<std::thread> threads;
    for (int i = 0; i < 5; i++) {
        threads.push_back(std::thread([&nums, i](){
            std::for_each(nums.begin() + i * 2, nums.begin() + (i + 1) * 2, print_num);
        }));
    }

    // 等待所有线程结束
    for (auto& thread : threads) {
        thread.join();
    }

    return 0;
}

以上代码创建了一个包含 10 个数字的 vector,并创建了 5 个线程,每个线程输出其中的两个数字。通过使用 STL 的 std::thread 类,我们可以轻松地创建多个并发线程。在这个例子中,我们使用了 C++11 中的 lambda 表达式来定义线程函数。最后,我们通过调用每个线程的 join() 方法,等待它们全部结束。

注意:join() 方法是 std::thread 类的一个成员函数,用于等待线程执行完毕并回收线程资源。当调用 join() 方法时,调用线程会阻塞在 join() 方法上,直到被调用线程执行完毕并退出

二、STL 应用实例

STL(Standard Template Library)是C++语言中的一个标准库,提供了许多常用的数据结构和算法,如容器、迭代器、算法等,可以大大提高C++程序的开发效率和代码可重用性。

1、STL 在数据结构中的应用

(1)数组:STL中有一个数组模板类vector,可以方便地实现动态数组,支持插入、删除、查找等操作。

(2)链表:STL中有一个链表模板类list,可以方便地实现双向链表,支持插入、删除、查找等操作。

(3)栈和队列:STL中有模板类stack和queue,可以方便地实现栈和队列,支持入栈、出栈、入队、出队等操作。

(4)堆:STL中有模板类priority_queue,可以方便地实现堆,支持插入、删除、查找最大值等操作。

(5)树:STL中有模板类set和map,可以方便地实现红黑树,支持插入、删除、查找等操作。

总之,STL提供了一系列高效、灵活的数据结构和算法,可以大大简化数据结构的实现和使用。

2、STL 在算法设计中的应用

(1)提供了丰富的容器类型,如vector、list、map等,可以方便地存储和管理数据,避免手动管理内存的麻烦。

(2)提供了大量的算法函数,如排序、查找、合并等,可以直接调用,避免重复造轮子,同时也提高了代码的可读性和可维护性。

(3)提供了迭代器的概念,可以方便地遍历容器中的元素,支持各种迭代器操作,如++、--、*、->等,可以帮助我们更加方便地处理数据。

(4)提供了函数对象(Functor)的概念,可以将函数封装为对象,使得函数可以像普通对象一样被传递和处理,同时也可以方便地实现各种算法。

总的来说,STL在算法设计中的应用非常广泛,可以帮助我们快速、高效地实现各种算法,从而提高程序的性能和可维护性。

3、STL 在实际工程中的应用

(1)容器类的使用:STL提供了许多容器类,如vector、list、map等,可以方便地存储和管理数据。在实际工程中,可以使用vector来存储一组数据,使用map来实现键值对的映射,使用list来实现链表等。

(2)算法类的使用:STL提供了许多常用的算法,如排序、查找、计数等,可以大大简化代码的编写。在实际工程中,可以使用STL提供的算法来实现一些常见的操作,如对容器中的元素进行排序、查找等。

(3)迭代器的使用:STL提供了迭代器的概念,可以方便地遍历容器中的元素。在实际工程中,可以使用迭代器来遍历容器中的元素,进行一些操作。

(4)函数对象的使用:STL提供了函数对象的概念,可以方便地对容器中的元素进行一些操作。在实际工程中,可以使用函数对象来对容器中的元素进行一些计算、比较等操作。

总之,STL在实际工程中的应用非常广泛,可以大大提高程序的开发效率和代码的可重用性。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值