alin的学习之路:c++11特性

tech2022-08-11  129

alin的学习之路:c++11 新特性

参考链接:https://blog.csdn.net/zzb2019/article/details/81624367

1. 关键字新增 auto decltype nullptr

1.1 自动类型推导 auto

auto a;// 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定a类型   auto i = 1;   auto d = 1.0;   auto str = "Hello World";   auto ch = 'A';   auto func = less<int>();   vector<int> iv;   auto ite = iv.begin();   auto p = new foo() // 对自定义类型进行类型推导 

1.2 decltype

decltype 则可以从一个变量或表达式中得到类型

int x = 3;decltype(x)y = x;

declype(x) 表示 int

1.3 nullptr

nullptr代表的是空指针,NULL实际上代表的是0

1.4 constexpr

近似const, 可以修饰变量,也可以修饰函数,

修饰变量如:

const int global = 100; int main () { int temp = 100; constexpr int a = 1; //right constexpr int b = global; //right constexpr int c = temp; //wrong }

既可以赋值字面常量也可以赋值以const变量

重点:constexpr修饰的函数,生效于编译时而不是运行时, 重点应用于修饰函数使其在编译期大幅度被解释 被constexpr修饰的函数,无论是普通函数,还是类成员函数,必须是编译器可计算得到结果,即字面常量,不可是运行时才能获取的内容

1.5 using 代替 typedef

typedef double db; //c99 using db = double; //c++11 typedef void(*function)(int, int);//c99,函数指针类型定义 using function = void(*)(int, int);//c++11,函数指针类型定义 using kvpairs = std::map<std::string, std::string>; //c++11 using CompareOperator = std::function<int (kvpairs &, kvpairs &)>; //c++11 using query_record = std::tuple<time_t, std::string>; //c++11 template<class T> using twins = std::pair<T, T>; //更广泛的还可以用于模板

2. 语法新特性

2.1 序列为循环(我理解为增强for循环)

map<int, int> mp; for(auto m : mp) { cout << m.first << " " << m.second << endl; }

2.2 更优雅的初始化方法

int arr[3]{1, 2, 3}; vector<int> iv{1, 2, 3}; map<int, string>{{1, "a"}, {2, "b"}}; string str{"Hello World"};

不是仅仅可以用vector等容器的那些构造函数

2.3 Lambda表达式

匿名函数

[] 中填=号可以获得和这个函数相同作用域的访问权限,常用于一些函数中套的小函数,比如:sort,for_each

如果在小括号和大括号中间有 -> ,代表返回值的类型

比如for_each(iv.begin(), iv.end(), [=](int &x)->int{return x * (a + b);});

vector<int> v; sort(v.begin(), v.end(), [](int v1, int v2){return v1 > v2;}); //降序排序

2.4 变长参数模板

auto t1 = make_tuple(1, 2.0, "C++ 11");   auto t2 = make_tuple(1, 2.0, "C++ 11", {1, 0, 2}); 

类似于python中的tuple操作

2.5 std::chrono时间相关

std::chrono::duration<double> duration //时间间隔 std::this_thread::sleep_for(duration); //sleep LOG(INFO) << "duration is " << duration.count() << std::endl; std::chrono::microseconds //微秒 std::chrono::seconds //秒 end = std::chrono::system_clock::now(); //获取当前时间

3. 原生字符串

字符串中有很多特殊字符需要转义,造成了书写出来会不太方便看,原生字符串解决了这个问题

string path = R"(C:\Program Files\Microsoft.NET\ADOMD.NET)";

从上面的例子中可以看出,它的语法格式如下:

字符串前加’R’前缀字符串首尾加上括号()

4. 容器

4.1 std::array

include <array> int main() { std::array<int, 4> arrayDemo = { 1,2,3,4 }; std::cout << "arrayDemo:" << std::endl; for (auto itor : arrayDemo) { std::cout << itor << std::endl; } int arrayDemoSize = sizeof(arrayDemo); std::cout << "arrayDemo size:" << arrayDemoSize << std::endl; return 0; }

4.2 std::forward_list

与list区分,list是双向链表,std::forward_list是单向链表

在插入和删除时候,使用链表比线性表的效率要高

4.3 std::unordered_map

与map的区别在于插入一个数据后不会自动排序,内部结构与map不同,map是红黑树,std::unordered_map是哈希表。

在查询时间上,时间复杂度是O(1) ,但是空间复杂度上是O(n)

4.4 std::unordered_set

存储依然是哈希表的方式,在插入时不会自动排序

5. c++11风格的指针

5.1 函数指针

int func1 (int a, int b) { return a + b; } auto a = 1, b = 2; std::function<int (int, int)> modify_add0(func1); LOG(INFO) << "directly assign function: " << modify_add0(a, b);

通过指定返回值、参数列表、绑定的函数和函数名,定义一个函数(指针) modify_add0 绑定的函数,可以是普通函数,也可以是类成员函数,同时指定:

class ca { public: bool func(int a) { LOG(INFO) << "aaa: " << a; } }; ca o; std::function<bool (int)> f = std::bind(&ca::func, o, std::placeholders::_1); f(1);

原先只有在boost出现且极为受限的函数占位符,也加入到了标准库,即std::placeholders,传递自定义参数绑定类成员函数时,需要配合使用std:bind。

bind和placeholders,同样可以用于普通函数:

int func1 (int a, int b) { b = a + a + a; return a + b; } auto a = 1, b = 2; auto auto1 = std::bind(func1, std::placeholders::_1, std::placeholders::_2); LOG(INFO) << "directly run auto: " << auto1(a, b);

5.2 std::unique_ptr

功能基本对应boost的scoped_ptr,或之前stl的auto_ptr,生命周期随构造者,reset自动析构再重新构造,get判断是否有效、支持放在容器内;

5.3 std::shared_ptr

功能对于boost的shared_ptr,可以有多个持有者的共享指针,即所谓引用计数型指针,直到最后一个持有者delete释放时,其指向的资源才会真正被释放。 典型应用案例:如对同一个全局无锁队列对象由shared_ptr封装,多线程的多个持有者均持有对其的引用。直到全部线程都释放掉对其的引用时,该无锁队列对象才会被最终销毁。 也就是shared_ptr适合用于管理“全局动态资源”。 std::make_shared封装了new方法,boost::make_shared之前的原则是既然释放资源delete由智能指针负责,那么应该把new封装起来,否则会让人觉得自己调用了new,但没有调用delete,似乎与谁申请,谁释放的原则不符。

5.4 std::weak_ptr

std::weak_ptr网上很多人说其实是为了解决std::shared_ptr在相互引用的情况下出现的问题而存在的,C++官网对这个只能指针的解释也不多,那就先甭管那么多了,让我们暂时完全接受这个观点。 std::weak_ptr有什么特点呢?与std::shared_ptr最大的差别是在赋值时,不会引起智能指针计数增加。lock返回一个指向共享对象的shared_ptr。与任何其它shared_ptr类似,只要此shared_ptr存在,它所指向的底层对象也就会一直存在。

6. 多线程与互斥同步

6.1 std::thread

std::thread为C++11的线程类,使用方法和boost接口一样,非常方便,同时,C++11的std::thread解决了boost::thread中构成参数限制的问题,我想着都是得益于C++11的可变参数的设计风格。

#include <thread> void threadfun1() { std::cout << "threadfun1 - 1\r\n" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "threadfun1 - 2" << std::endl; } void threadfun2(int iParam, std::string sParam) { std::cout << "threadfun2 - 1" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(5)); std::cout << "threadfun2 - 2" << std::endl; } int main() { std::thread t1(threadfun1); std::thread t2(threadfun2, 10, "abc"); t1.join(); std::cout << "join" << std::endl; t2.detach(); std::cout << "detach" << std::endl; }

6.2 原子变量

std::atomic 用于多线程资源互斥操作,属c++11重大提升,多线程原子操作简单了许多。 从功能上看,简单地说,原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的类型。从实现上,大家可以理解为这些原子类型内部自己加了锁。

#include <thread> #include <atomic> #include <stdio.h> std::atomic_bool bIsReady = false; std::atomic_int iCount = 100; void threadfun1() { if (!bIsReady) { std::this_thread::yield(); } while (iCount > 0) { printf("iCount:%d\r\n", iCount--); } } int main() { std::atomic_bool b; std::list<std::thread> lstThread; for (int i = 0; i < 10; ++i) { lstThread.push_back(std::thread(threadfun1)); } for (auto& th : lstThread) { th.join(); } }

6.3 std::condition_variable

C++11中的std::condition_variable就像Linux下使用pthread_cond_wait和pthread_cond_signal一样,可以让线程休眠,直到别唤醒,现在在从新执行。线程等待在多线程编程中使用非常频繁,经常需要等待一些异步执行的条件的返回结果。

// condition_variable example #include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variable std::mutex mtx; std::condition_variable cv; bool ready = false; void print_id(int id) { std::unique_lock<std::mutex> lck(mtx); while (!ready) cv.wait(lck); // ... std::cout << "thread " << id << '\n'; } void go() { std::unique_lock<std::mutex> lck(mtx); ready = true; cv.notify_all(); } int main() { std::thread threads[10]; // spawn 10 threads: for (int i = 0; i<10; ++i) threads[i] = std::thread(print_id, i); std::cout << "10 threads ready to race...\n"; go(); // go! for (auto& th : threads) th.join(); return 0; }
最新回复(0)