C++最佳实践之常用库介绍
C++的常用库包括:algorithm、chrono、iostream、future、memory、map、queue、unordered_map、regex、set、string、sstream、stdexcept、thread、vector、mutex等。熟悉这些C++库对我们开发有很大帮助,我们结合代码实践来介绍。
目录
一、algorithm算法
1、最小值与最大值
2、排序
3、二分查找
4、反转
5、替换
二、chrono时钟
三、iostream输入输出流
1、ios.h
2、istream.h
3、ostream.h
四、future异步任务
五、memory内存管理
六、map与unordered_map
七、queue队列
八、regex正则匹配
九、set集合
十、string字符串操作
十一、字符串格式化
十二、标准异常
十三、vector容器
十四、互斥锁
十五、thread线程库
一、algorithm算法
algorithm库包括:min、max、sort、binary_search、reverse、replace等函数。部分源码如下:
template <class T>const T& min(const T& a, const T& b);template <class T>const T& max(const T& a, const T& b);template <class RandomAccessIterator>void sort(RandomAccessIterator first, RandomAccessIterator last);template <class ForwardIterator, class T>bool binary_search(ForwardIterator first, ForwardIterator last, const T& value);template <class BidirectionalIterator>void reverse(BidirectionalIterator first, BidirectionalIterator last);template <class ForwardIterator, class T>void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value);
1、最小值与最大值
使用min()求两者最小值,用max()求两者最大值。示例如下:
int a = 1, b = 2;int min = std::min(a, b);int max = std::max(a, b);
2、排序
使用sort()进行排序,接受的参数为iterator迭代器,示例如下:
std::vector<int> array{3, 6, 1, 5, 9, 2, 8};std::sort(array.begin(), array.end());for (int it: array) {printf("%d ", it);}
3、二分查找
二分查找是基于有序数组使用二分法进行查找,如果找到返回true。示例如下:
bool result = std::binary_search(array.begin(), array.end(), 8);
4、反转
反转是把迭代器从头到尾反过来,比如一个升序数组反转后变成降序数组。示例如下:
std::reverse(array.begin(), array.end());
5、替换
替换是遍历迭代器把就内容替换为新内容,示例如下:
std::replace(array.begin(), array.end(), 6, 666);
二、chrono时钟
在chrono库提供时间单位有:时、分、秒、毫秒、微秒、纳秒。如下表所示:
chrono::hours | 时 |
chrono::minutes | 分 |
chrono::seconds | 秒 |
chrono::milliseconds | 毫秒 |
chrono::microseconds | 微秒 |
chrono::nanoseconds | 纳秒 |
使用chrono可以获取日期、当前时间,也可以计算时间差。示例如下:
using namespace std::chrono;system_clock::time_point time_point = system_clock::now();// 获取日期time_t time = system_clock::to_time_t(time_point);printf("date=%s", ctime(&time));// 获取当前时间,单位mslong time_millis = time_point.time_since_epoch().count() / 1000;printf("current millisecond=%ld", time_millis);// 计算时间差system_clock::time_point begin = system_clock::now();int sum;for (int i = 0; i < 10000; ++i) {sum += i;}system_clock::time_point end = system_clock::now();duration<double> diff = duration_cast<duration<double>>(end - begin);printf("use time=%lf", diff.count());
三、iostream输入输出流
输入输出流定义在iostream.h头文件中,内部包含ios.h、istream.h、ostream.h。而fstream.h提供打开和关闭文件的函数。
1、ios.h
ios头文件提供打开文件的模式,还有seek模式。其中打开文件模式如下表所示:
ios::app | 以追加方式打开 |
ios::ate | 文件打开后定位到文件尾 |
ios::binary | 以二进制方式打开 |
ios::in | 以输入方式打开(读) |
ios::out | 以输出方式打开(写) |
ios::nocreate | 不建立文件,文件不存在时打开失败 |
ios::noreplace | 不覆盖文件,文件存在时打开失败 |
ios::trunc | 如果文件存在,把文件长度设为0 |
seek模式包括:从头开始、当前位置和尾部开始,枚举定义如下:
enum seekdir {beg, cur, end};
2、istream.h
istream头文件提供输入流操作,源码定义如下:
// 读一个字符basic_istream& get(char_type& c);// 读取一行basic_istream& getline(char_type* s, streamsize n);// 读取指定长度的内容basic_istream& read (char_type* s, streamsize n);// 读模式的seekbasic_istream& seekg(off_type, ios_base::seekdir);
3、ostream.h
ostream头文件提供输出流操作,源码定义如下:
// 写一个字符basic_ostream& put(char_type c);// 写入指定长度的内容basic_ostream& write(const char_type* s, streamsize n);// 刷新basic_ostream& flush();// 获取当前位置pos_type tellp();// 绝对位置的seekbasic_ostream& seekp(pos_type);// 指定模式的seekbasic_ostream& seekp(off_type, ios_base::seekdir);
四、future异步任务
future用于执行异步任务,等待执行结束后用get()获取结果。我们可以从packaged_task获取future,或者从async()获取future,也可以从promise获取future。示例如下:
// 从packaged_task获取futurestd::packaged_task<int()> task([] { return 1; });std::future<int> f1 = task.get_future();std::thread t(std::move(task)); // 启动线程// 从async()获取futurestd::future<int> f2 = std::async(std::launch::async, [] { return 2; });// 从promise获取futurestd::promise<int> p;std::future<int> f3 = p.get_future();std::thread([&p] { p.set_value_at_thread_exit(3); }).detach();f1.wait();f2.wait();f3.wait();t.join();printf("f1=%d, f2=%d, f3=%d\n", f1.get(), f2.get(), f3.get());
五、memory内存管理
memory头文件提供四种智能指针:shared_ptr、unique_ptr、weak_ptr和auto_ptr。其中auto_ptr已经过时。智能指针的特性对比如下:
shared_ptr | 共享指针,使用引用计数 |
unique_ptr | 单一指针,一般用在单例场景 |
weak_ptr | 弱指针,对共享指针进行观察 |
另外提供allocator分配器,使用示例如下:
std::allocator<int> allocator;int size = 3;// 分配内存块int *ptr = allocator.allocate(size);// 给每个内存地址赋值allocator.construct(ptr, 1);allocator.construct(ptr + 1, 2);allocator.construct(ptr + 2, 3);for (int i = 0; i < size; i++) {printf("alloc=%d", *(ptr + i));// 释放对应的内存地址allocator.destroy(ptr + i);}// 释放内存块allocator.deallocate(ptr, size);
六、map与unordered_map
C++提供map和unordered_map两种数据结构。其中map基于红黑树,unordered_map基于哈希表。优缺点对比如下:
优点 | 缺点 | |
map | 基于红黑树有序,操作时间复杂度lgn | 保存父节点和子节点,空间复杂度高 |
unordered_map | 基于哈希查找效率高 | 无序,建立哈希表耗时 |
map的操作示例如下:
std::map<int, std::string> map;// addmap.insert(std::pair<int, std::string>(1, "ferrari"));map.insert(std::pair<int, std::string>(2, "lanbojini"));map.insert(std::pair<int, std::string>(3, "rollsroyce"));map.insert(std::pair<int, std::string>(6, "benzi"));// removemap.erase(6);// 遍历for (auto it = map.begin(); it != map.end(); it++) {printf("key=%d, value=%s", it->first, it->second.c_str());}// findauto it = map.find(3);if (it != map.end()) {printf("found value=%s", it->second.c_str());}
七、queue队列
queue队列是FIFO先进先出,与queue相反的是stack,属于LIFO后进先出。我们来看看队列的操作示例:
std::queue<int> queue;// 入队queue.push(111);queue.push(222);queue.push(333);printf("queue front=%d, back=%d", queue.front(), queue.back());// 出队while (!queue.empty()) {int front = queue.front();queue.pop();}
八、regex正则匹配
regex库是C++提供的正则匹配。示例如下:
// 匹配规则std::regex regular(".{5},\\d{4}");std::string str_in("hello,2022");// 匹配结果std::smatch result;// 调用正则匹配if (std::regex_match(str_in, result, regular)) {for (int i = 0; i < result.size(); ++i) {LOGE("match=%s", result[i].first);}}
九、set集合
set是不重复key的集合,保证key的唯一性。示例如下:
std::set<std::string> set;set.insert("hello");set.insert("world");printf("size=%lu\n", set.size());if (auto it = set.find("hello") != set.end()) {printf("find result=%d\n", it);}set.erase("hello");set.clear();
十、string字符串操作
字符串操作包括:拼接、删除、截取、替换、判断是否相等。使用示例如下:
std::string str("hello");// 后面追加str.append(" world");// 前面插入str.insert(0, "ok,");// 截取子字符串str = str.substr(3);printf("sub str=%s\n", str.c_str());// 空格替换为逗号for (int i = 0; i < str.size(); ++i) {char ch = str.at(i);if (ch == ' ') {str.replace(i, 1, 1, ',');}}// 后面添加字符str.push_back('!');// 删除指定位置的字符str.erase(str.size() - 1);size_t pos = str.find("world");printf("find pos=%ld\n", pos);// 判断字符串是否相等,==属于操作符重载if (str == "hello,world") {// ...}
十一、字符串格式化
在C语言中,我们可以使用sprintf()函数进行字符串格式化输出,整型用%d,浮点型用%f,长整型用%ld,字符串用%s。在Java语言中,可以使用StringFormat进行格式化。今天的主角是C++的sstream库,提供stringstream进行字符串格式化。示例如下:
// 字符串格式化std::stringstream stream;int a = 10;float b = 3.5;long c = 666;stream << "a=" << a << ", b=" << b << ", c=" << c;printf("stream:%s", stream.str().c_str());
十二、标准异常
C++在stdexcept库提供标准异常。基类是exception,位于exception.h,源码如下:
class exception{public:exception() _NOEXCEPT {}virtual ~exception() _NOEXCEPT;virtual const char* what() const _NOEXCEPT;};
继承exception的类如下表所示:
bad_exception | 破坏异常,位于exception.h |
bad_alloc | 分配异常,位于new.h |
bad_cast | 转换异常,位于typeinfo.h |
logic_error | 逻辑错误,位于stdexcept.h |
runtime_error | 运行时错误,位于stdexcept.h |
继承logic_error的类如下表所示:
out_of_range | 数组越界 |
length_error | 长度错误 |
invalid_argument | 无效参数 |
domain_error | 域错误 |
继承runtime_error的类如下表所示:
range_error | 边界错误 |
overflow_error | 内存上溢 |
underflow_error | 内存下溢 |
十三、vector容器
vector是一个容器,基于模板类,理论上可支持任意类型。与数组区别是,vector可以动态扩容。另外,vector有begin()和end()迭代器。相关操作示例如下:
std::vector<int> vector;// 尾部压入vector.push_back(2);// 指定位置插入vector.insert(vector.begin(), 1);vector.push_back(3);// 迭代器遍历for (auto it = vector.begin(); it != vector.end(); it++) {printf("val=%d\n", *it);}// 获取头部和尾部数值int front = vector.front();int back = vector.back();// 移除首位的数值vector.erase(vector.begin());// 尾部弹出vector.pop_back();// 清空容器vector.clear();
十四、互斥锁
C++提供的互斥锁有:lock_guard、unique_lock、shared_lock和scoped_lock。对比如下:
lock_guard | 互斥锁包装器,构造时上锁,析构时解锁 |
unique_lock | 单一锁,可手动释放锁,锁的粒度更细 |
shared_lock | 共享锁,以共享模式锁住互斥,c++14 |
scoped_lock | 作用域锁,接受多个mutex,c++17 |
十五、thread线程库
C++的线程库是对pthread的封装,可以使用join启动,也可以使用detach启动。其中,join会让主线程等待子线程执行结束;而detach是把子线程分离出来,与主线程互不影响。下面是两个线程交替打印数字,模拟多线程同步的示例:
bool flag;
std::mutex mtx;
std::condition_variable cond;void task1() {for (int i = 0; i < 10; ++i) {std::unique_lock<std::mutex> lock(mtx);cond.wait(lock, []() {return flag;});if (i % 2 == 0) {printf("%s, count=%d\n", __func__, i);}flag = !flag;cond.notify_one();lock.unlock();}
}void task2() {for (int i = 0; i < 10; ++i) {std::unique_lock<std::mutex> lock(mtx);cond.wait(lock, []() {return !flag;});if (i % 2 == 1) {printf("%s, count=%d\n", __FUNCTION__, i);}flag = !flag;cond.notify_one();lock.unlock();}
}
然后是分别创建启动两个打印线程,奇偶交替打印输出:
std::thread thread1(task1);std::thread thread2(task2);thread1.detach();thread2.detach();
C++最佳实践之常用库介绍相关推荐
- Python水文模型常用库介绍
Python 特别用作现有程序的粘合剂,无论是用 C 还是 FORTRAN 编写的.对于想要开始使用 Python 的人(对于水文学家),我建议看一下本篇博客介绍的资源. (1) 常用库介绍 CFM ...
- 第二章(1):Python入门:语法基础、面向对象编程和常用库介绍
第二章(1):Python入门:语法基础.面向对象编程和常用库介绍 目录 第二章(1):Python入门:语法基础.面向对象编程和常用库介绍 1. Python 简介 1.1 Python 是什么? ...
- Python之数据挖掘实践--scikit learn库介绍和下载、实践、采坑
文章目录 前言 A sklearn库是什么? A1 依赖库介绍 1.Numpy库 2.Scipy库 3. matplotlib A2 下载安装 B 实践过程 B1 主成分分析(PCA) B2 实现Km ...
- 玩转ECS第8讲 | 服务器迁移中心SMC最佳实践及新特性介绍
简介:本次分享由阿里云技术专家白辉万(百宝)为大家介绍免费的服务器迁移上云最佳实践方案和新功能特性,包括一键迁云.自动定期同步.一键验证.本次分享内容将帮助企业上云客户越过高高的服务器迁移门槛,快速体 ...
- 玩转ECS第5讲 | 弹性计算安全组最佳实践及新特性介绍
简介:本次内容由阿里云智能技术专家王帝(丞浩)为大家介绍如何正确使用安全组.最佳实践以及新特性:详细了解安全组为何是云端的虚拟防火墙,以及为何是重要的网络隔离手段. 演讲嘉宾简介:王帝(丞浩),阿里云 ...
- [转]Android最佳实践之:StrictMode介绍
[IT168技术]最新的Android平台中(Android 2.3起),新增加了一个新的类,叫StrictMode(android.os.StrictMode).这个类可以用来帮助开发者改进他们编写 ...
- Linux环境配置Python库及常用库介绍
Linux环境配置Python库 Python 的标准库包括了很多的模块, 从 Python 语言自身特定的类型和声明, 到一些只用于少数程序的不著名的模块.在 Linux环境 运行Python 经常 ...
- boost库 tbb_boost库常用库介绍
在文本处理部分,conversion/lexcial_cast类用于"用C++"的方法实现数字类型和字符串之间的转换. 主要是替代C标准库中的 atoi. itoa之类的函数.当然 ...
- 房地产最佳实践(RERCS)整体方案 介绍
目录 RERCS Business Overview-RRCS 业务概览 RERCS System Architecture-RERCS 系统架构 RERCS Development-FPM Over ...
最新文章
- 2021湖北省普通高考成绩查询果,2021年湖北高考录取结果查询登录网址入口
- C语言基础排序算法-冒泡排序
- java webpack_webpack将对象暴露为全局
- idea 代码格式化插件_IDEA非常棒的插件,阿里巴巴约定成文的代码公约规范
- 七 web爬虫讲解2—urllib库爬虫—状态吗—异常处理—浏览器伪装技术、设置用户代理...
- 实施和开发哪个前景好_「深圳app开发」app模板开发和app定制开发哪个好呢?
- 正点原子 潘多拉stlink驱动_「正点原子Linux连载」第五十六章Linux自带的LED灯驱动实验...
- 最小的浏览器-橘子浏览器才1M大小
- python,NSGA3 多目标优化,结合多进程,可用于swat模型等复杂模型。
- 图像算法之3D人脸识别技术原理概述
- 【总目录】机器学习原理剖析、开源实战项目、全套学习指南(50篇合集)
- 同IP不同端口导致session冲突的解决方法
- java.sql.BatchUpdateException: Data truncation: Division by 0
- 【FPGA的小娱乐】tft显示屏生成信号辅助测试阵列
- SCAFFOLD: Stochastic Controlled Averaging for Federated Learning
- H3C交换机如何进行批量端口配置
- html中两个日期相减,在Excel中如何让两个时间相减?
- 不干正事儿系列文章1:Sonic Pi简单应用
- 【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层驱动代码分析
- golang使用os\exec执行高级命令