1:auto类型推导
基本用法:
double func();
auto a = 1; //int
auto b = func(); //double
//简化复杂的变量类型
vector<string> vstr;
vector<string>::iterator it = vstr.begin();
//用auto声明
auto it = vstr.begin();
2:基于范围的for循环
基本用法:
//基于范围的for循环后的括号由冒号“:”分为两部分,第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围
int arr[5] = { 0, 1, 2, 3, 4};
for (auto& it : arr) //auto&:修改arr; auto:不修改arr,拷贝对象
cout << it << endl;
注意:此基于范围的for循环对于数组的大小必须确定,否则不能使用该for,动态数组也不行
3:智能指针
头文件#include <memory>
总共四个智能指针:auto_ptr, unique_ptr, shared_ptr, weak_ptr(其中auto_ptr已弃用)
3.1:unique_ptr:
又被称为独有智能指针,该指针所管理的对象只能指定一个,同时不允许通过拷贝和赋值运算符赋值给另一个unique_ptr。
#include <iostream>
#include <memory>
#include <windows.h>
using namespace std;
class A
{
};
int main()
{
/*初始化unique_ptr*/
//初始化方式1
unique_ptr<A> Aa_1(new A); //对类的初始化
unique_ptr<char> Aa_11(new char(0)); //对变量的初始化
//初始化方式2
unique_ptr<A> Aa_2;
Aa_2.reset(new A);
unique_ptr<char> Aa_22;
Aa_22.reset(new char(0));
//初始化方式3(C++14后加入,推荐用此方式来初始化对象)
unique_ptr<A> Aa_3(make_unique<A>());
unique_ptr<char> Aa_33(make_unique<char>(0));
//一组堆对象的初始化
unique_ptr<char[]> SendBuf_1(new char[10]); //开辟空间但是全为垃圾值,需要手动memset
unique_ptr<char[]> SendBuf_2(make_unique<char[]>(10)); //开辟空间同时赋默认值0,推荐此方法
/*unique_ptr由于是独占的智能指针 无法通过赋值拷贝,但是有move方法将unique_ptr 对象持有的堆内存转移给另外一个unique_ptr,move之后原对象为空*/
unique_ptr<A> Aa_Temp(move(Aa_1));
/*方法*/
char* buf = SendBuf_2.release(); //返回管理的指针,并将管理的指针替换为空,同时释放管理指针所有权
SendBuf_2.reset(); //(如果当前有unique_ptr管理)释放当前管理的指针,然后unique_ptr置空
SendBuf_2.get(); //返回当前管理的指针,并不会释放unique_ptr的所有权,但是可以通过该方法对内存进行操作。注意:不能将返回的指针进行delete,因为所有权还是在unique_ptr。
return 0;
}
3.2:shared_ptr
共享智能指针,和unique_ptr不同的是它可以在多个shared_ptr之间进行共享,每共享一次,当前资源应用计数将增加1(通过.use_count()获取资源引用次数),其他用法和unique_ptr基本相同
3.3:weak_ptr
weak_ptr的引入目的是为了协助shared_ptr进行工作,他是对对象的一种弱引用,同时不参与管理对象声明周期(资源应用计数不会改变)
总结:
通常情况下,如果资源不需要在其他地方共享,那么应该优先使用unique_ptr,反之使用 shared_ptr,当然这是在该智能指针需要管理资源的生命周期的情况下;如果不需要管理对象的生命周期,则使用 weak_ptr
4:原子变量
头文件:#include <atomic>
std::atomic<T>
C++11提供的一个原子类型,他所管理的变量称为原子变量,可以指定任意数据类型作为原子变量;
原子操作:原子操作指的是不会被线程调度机制打断的操作,原子操作一旦开始,就会一直运行到结束,不会出现CPU上下文切换,而多线程中抢占资源造成数据混乱根本问题就是源自CPU上下文切换,因此原子变量可以解决该问题,替代掉互斥锁。
4.1:使用基本变量进行测试
#include <cstdio>
#include <atomic>
#include <iostream>
#include <thread>
using namespace std;
int num(0); //使用基本类型变量
void func()
{
for (int i = 0; i < 1000000; i++)
num++;
}
int main()
{
thread t1(func);
thread t2(func);
thread t3(func);
thread t4(func);
thread t5(func);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
cout << num << endl;
return 0;
}
结果:
4.2:使用原子类型进行测试
#include <cstdio>
#include <atomic>
#include <iostream>
#include <thread>
using namespace std;
atomic_int num(0); //使用原子变量
void func()
{
for (int i = 0; i < 1000000; i++)
num++;
}
int main()
{
thread t1(func);
thread t2(func);
thread t3(func);
thread t4(func);
thread t5(func);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
cout << num << endl;
return 0;
}
结果: