列表初始化
C++11中为了同一初始化方式,提出了列表初始化的概念 在C++11中初始化列表可以作用于任何类型对象的初始化
struct Point
{
int x;
int y;
}a = {1,2};
int b{ 3 };
int c = { 3 };
int* d = new int{ 3 };
double b = double{ 12.12 };
int* arr = new int[] {1, 2, 3};
std::map<int, int>map_t{ {1,2},{2,3},{4,5} };
std::list<std::string>list_str{ "hello""world","cha" };
列表初始化可以阻止类型收窄
比如隐式转换float->int 列表初始化就可以编译期报错 高精度转低精度,整形转浮点,整形转低长度整形都会类型收窄,用列表初始化就可以预防,直接编译期报错
for新写法
注意:如果传引用遍历修改容器 会造成迭代器失效
void printElem(int& i)
{
cout << i << endl;
}
int main()
{
vector<int>arr{1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 0; i < arr.size(); i++)
cout << arr[i] << ' ';
cout << endl;
for (auto it = arr.begin(); it != arr.end(); it++)
cout << *it << ' ';
cout << endl;
for_each(arr.begin(), arr.end(), printElem);//把元素中每个元素传给printElem
//C++11
for (auto n : arr) //值传递
{
cout << n << ' ';
}
for (auto &n : arr) //值引用传递
{
cout << n << ' ';
}
cout << endl;
}
注意:如果引用传递的时候修改容器,迭代器会失效?
for (auto &n : arr) //引用传递
{
cout << n << ' ';
//arr.push_back(1);
}
枚举类(强类型枚举)
enum xxx{r,b,g}; 缺点:全局作用域,允许隐式转换为整型,占用存储空间以及符号性不确定
C++11:
enum class XXX{r,b,g}; XXX c?= XXX::r;//ok 可以enum class Color:char{r,b,g}//指定空间。默认为4,现在为1
enum class Color:char //指定枚举类占用的空间
{
red,
blue,
green
};
int main()
{
Color c = Color::red; //改变作用域
int x = (int)Color::red; //取消隐式转换
cout<<sizeof(c);//输出1
}
类型别名声明:using 与 typedef
typedef unsigned int uint; using uint = unsigned int;? 看起来也更符合正常人的书写
typedef std::unique_ptr<std::unordered_map<std::string, int>> UPtrMapSI; using UPtrMapSI = std::unique_ptr<std::unordered_map<std::string, int>>;
typedef ?void(*FP)(int, string&);? //没见过的可能还真不认识它 using FP = void(*)(int, string&);
template<typename T> typedef std::vector<T>v;//报错! typedef不支持模板
template<typename T> using v = std::vector<T>;
直接提供多线程支持
线程的创建: 以前是直接用平台相关的API :pthread_create / _beginthread / CreateThread C++11: std::thread t(func,param);//#include<thread>
锁: mutex //#include<mutex> recursive_mutex timed_mutex recursive_timed_mutex
std::mutex g_lock;//创建锁
void thrfunc(int param) {
g_lock.lock();//加锁
cout << "thread:" << param << endl;
g_lock.unlock();
}
int main()
{
std::thread t1(thrfunc, 1);
std::thread t2(thrfunc, 2);
t1.join();
t2.join();//等待退出
}
原子变量: atomic<int> / atomic_int? ? //#include<atomic>
#include<atomic>
int g_num{ 0 };
std::atomic<int> g_val{ 0 };//原子变量
void thrfunc(int param) {
for (int i = 0; i < 1000; i++) {
g_val++;
g_num++;
}
}
int main()
{
std::thread t1(thrfunc, 1);
std::thread t2(thrfunc, 2);
t1.join();
t2.join();//等待退出
cout << g_val<<endl<<g_num;
}
条件变量: 类似于事件,多线程里线程和线程之间互相通知对方发生了什么事情,进行协作 std::condition_variable cv; cv.wait(i);//等一个事件 cv.notify_one();//通知一个线程 cv.notify_all();//通知所有线程
std::call_once/std::once_flag: 多个线程要访问同一个函数,只有一个线程会成功
std::promise ?std::future: promise对象可以保存某一类型T的值,该值可被future对象读取(可在另外一个线程中),一次promise也提供了一种线程同步手段
std::packaged_task: 包装一个可调用对象,并且允许异步获取改可调用对象的结果,std::packaged_task与std::function类似不过std::packaged_task将其包装的可调用对象传递给一个std::futrue对象(该对象通常在另外一个线程中获取std::packaged_task任务的执行结果)
std::async: 异步接口std::async,可以方便的获取线程函数的执行结果,它会自动创建一个线程去调用线程函数,返回一个std::futrue,其中存放了线程函数的返回结果,当需要异步操作的结果时,直接从futrue中取出,std::async先将异步操作用std::packaged_task包装起来,然后异步操作的结果放在std::promise中,这个过程就是创造std::futrue的过程,外面在通过futrue,get/wait来获取这个结果,因此不用再想该怎么调用std::futrue、std::promise和std::packaged_task了,std::async已经搞定一切,std::async异步操作不用关注线程创建内部细节,就能获取异步执行状态和结果,还可以指定线程创建策略,推荐用std::async代替线程创建,让它称为异步操作的首选
?
|