c++11常用特性

目录

 

一、atomic

1、std::atomic_flag

2、 std::atomic

二、std::thread

三、std::condition_variable

四、右值引用

五、std::function、std::bind

六、Lambda表达式


一、atomic

1、std::atomic_flag

atomic_flag 一种简单的原子布尔类型,只支持两种操作,test-and-set 和 clear。

std::atomic_flag 只有默认构造函数,拷贝构造函数已被禁用

ATOMIC_FLAG_INIT: 如果某个 std::atomic_flag 对象使用该宏初始化,那么可以保证该 std::atomic_flag 对象在创建时处于 clear 状态。

test_and_set() :检查 std::atomic_flag 标志,如果 std::atomic_flag 之前没有被设置过,则设置 std::atomic_flag 的标志,并返回先前该 std::atomic_flag 对象是否被设置过,如果之前 std::atomic_flag 对象已被设置,则返回 true,否则返回 false。

clear():清除 std::atomic_flag 对象的标志位,即设置 atomic_flag 的值为 false。

由此可以构造一个简单的锁

std::atomic_flag lock = ATOMIC_FLAG_INIT;   //clear 状态  

while (lock.test_and_set());                //返回false,同时设置atomic_flag的标志,之后其
/* */                                       //他线程调用此函数都返回true                           
lock.clear();                               //重置为 clear 状态,其他线程开始抢占 

2、 std::atomic

std::atomic为C++11封装的原子数据类型。

先上张图:

以上就是支持的数据类型。

原子操作好像是在汇编上实现的,所以速度要比各种锁快上不少(好像)

除此之外,还可以进行std::atomic<T>模板类使对象操作为原子操作。

二、std::thread

#include <iostream>
#include <thread>
using namespace std;
void fun1()
{
    cout<<"fun1"<<endl;
}

void fun2(int a)
{
    cout<<a<<endl;
    cout<<"fun2"<<endl;
}

int main()
{
    thread t1(fun1);
    thread t2(fun2, 10);
    t1.join();
    t2.detach();
    return 0;
}

在程序运行时,会出现以下的几种情况:

1、主线程先运行结束

2、子线程先运行结束

3、主子线程同时结束

join()函数是一个等待线程完成函数,主线程需要等待子线程运行结束了才可以结束,在实例程序中,t1.join()会等待t1线程退出后才继续往下执行。

detach()是分离线程函数,使用detach()函数会让线程在后台运行,即说明主线程不会等待子线程运行结束才结束。

三、std::condition_variable

std::condition_variable一般与std::unique_lock配合使用

std::condition_variable类的成员函数:

(1)、构造函数:仅支持默认构造函数,拷贝、赋值和移动(move)均是被禁用的;

(2)、wait:当前线程调用wait()后将被阻塞,直到另外某个线程调用notify_*唤醒当前线程;当线程被阻塞时,该函数会自动调用std::mutex的unlock()释放锁,使得其它被阻塞在锁竞争上的线程得以继续执行。一旦当前线程获得通知wait()函数也是自动调用std::mutex的lock()

(3)、wait_for:与wait()类似,只是wait_for可以指定一个时间段,在当前线程收到通知或者指定的时间超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其它线程的通知,wait_for返回,剩下的步骤和wait类似;

(4)、wait_until:与wait_for类似,只是wait_until可以指定一个时间点,在当前线程收到通知或者指定的时间点超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其它线程的通知,wait_until返回,剩下的处理步骤和wait_until类似;

(5)、notify_all: 唤醒所有的wait线程,如果当前没有等待线程,则该函数什么也不做;

(6)、notify_one:唤醒某个wait线程,如果当前没有等待线程,则该函数什么也不做;如果同时存在多个等待线程,则唤醒某个线程是不确定的(unspecified);

四、右值引用

关于左值与右值:

一个左值表达式代表的是对象本身,而右值表达式代表的是对象的值;变量也是左值。

 

先看几行代码

int main()
{
    int b = 0;
    int &a = b;
    int &c = 0;
    return 0;
}

很明显,无法通过编译。

error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'|

引用是变量的别名,使用常量初始化引用是错误的。

当然,我们可以通过添加const来进行初始化,但不能对其的值进行修改。

右值引用:

int main()
{
    const int &c = 0;
    c = 2;
    cout<<c;
}

可以成功输出2.

底层实现:  先对一个临时变量赋值为0,在将临时变量储存到c中。

class A
{
public:
    int a;
};

A fun()
{
    return A();
}

int main()
{
    int &&c = 0;
    c = 2;
    A &&a = fun();
    return 0;
}

fun()返回的右值本来在表达式语句结束后,其生命也就该终结了(因为是临时变量),而通过右值引用,该右值又重获新生,其生命期将与右值引用类型变量a的生命期一样,只要a还活着,该右值临时变量将会一直存活下去。实际上就是给那个临时变量取了个名字。

五、std::function、std::bind

举个栗子:

#include <iostream>
#include <functional>
using namespace std;



class A
{
public:
    typedef int(*AddFun)(int, int);
    void Add(AddFun fun, int a, int b)
    {
        int sum = fun(a,b);
        cout<<sum<<endl;
    }

    void Add(function<int(int,int)> fun, int a,int b)
    {
        int sum = fun(a,b);
        cout<<sum<<endl;
    }
};

class B
{
public:
    int add(int a, int b)
    {
        return a + b;
    }
};

int add(int a, int b)
{
    return a + b;
}
int main()
{
    A   a;
    a.Add(add,1,2);

    B   b;
    a.Add(bind(&B::add,b,placeholders::_1,placeholders::_2),1,2);
    return 0;
}

std::bind第一个参数为对象函数指针,表示函数相对于类的首地址的偏移量;

testAdd为对象指针;

std::placeholders::_1和std::placeholders::_2为参数占位符,表示std::bind封装的可执行对象可以接受两个参数。

当然,也可以这么用:
 

void add(int a, int b)
{
    cout << a + b;
}

auto fun =  std::bind(add, std::placeholders::_1, std::placeholders::_2);
fun1(3, 1);

其中fun的类型就是function<int(int,int)>。

六、Lambda表达式

[capture list] (params list) mutable exception-> return type { function body }

capture list:捕获外部变量列表

params list:形参列表

mutable指示符:用来说用是否可以修改捕获的变量

exception:异常设定

return type:返回类型

function body:函数体

其中[capture list]:

1.[var]表示值传递方式捕捉变量var;
2.[=]表示值传递方式捕捉所有父作用域的变量(包括this);
3.[&var]表示引用传递捕捉变量var;
4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this);
5.[this]表示值传递方式捕捉当前的this指针。

int main()
{    
    auto fun = [](int a,int b){cout<<a+b;};
    fun(1,2);
    return 0;
}
/**    output: 3   **/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值