日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++】C++11 新特性

發(fā)布時(shí)間:2024/1/8 c/c++ 67 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++】C++11 新特性 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

1.列表初始化

1.1. C++98中使用{}初始化的問題

1.2. 內(nèi)置類型的列表初始化

1.3. 自定義類型的列表初始化

2. 變量類型推導(dǎo)

2.1. 為什么需要類型推導(dǎo)

2.2. decltype類型推導(dǎo)

2.2.1 為什么需要decltype

2.2.2. decltype

3. 對(duì)默認(rèn)成員的控制(default、delete)

3.1. 顯式缺省函數(shù)

3.2. 刪除默認(rèn)函數(shù)

3.3. final和override

4. 右值引用

4.1. 概念

4.2. 右值與左值

4.3. 左值引用與右值引用

4.4. 左值引用的缺陷

4.5. 移動(dòng)語義

4.6. 移動(dòng)構(gòu)造和移動(dòng)賦值

4.7. 完美轉(zhuǎn)發(fā)

5. lambda表達(dá)式

5.1. lambda表達(dá)式語法

6. 包裝器

6.1. 為什么需要包裝器

6.2. 包裝器的使用

6.3. bind包裝器

6.3.1. bind包裝器改變參數(shù)位置

6.3.2. bind包裝器綁定固定參數(shù)

7. thread線程庫

7.1. thread線程庫函數(shù)介紹

7.2. 線程函數(shù)參數(shù)

7.3. lock_guard與unique_lock

7.3.1. Mutex的種類

7.3.2. lock_guard

7.3.3. unique_lock

7.4. 原子性操作庫(atomic)

8. 條件變量(condition_variable)


1.列表初始化

1.1. C++98中使用{}初始化的問題

在C++98中,標(biāo)準(zhǔn)允許使用花括號(hào){}對(duì)數(shù)組元素進(jìn)行統(tǒng)一的列表初始值設(shè)定。比如:

int array1[] = {1,2,3,4,5}; int array2[5] = {0};

對(duì)于一些自定義的類型,卻無法使用這樣的初始化。比如:

vector<int> v{1,2,3,4,5};

就無法通過編譯,導(dǎo)致每次定義vector時(shí),都需要先把vector定義出來,然后使用循環(huán)對(duì)其賦初始值,非常不方便。C++11為了兼容C語言的這種特性,擴(kuò)大了用大括號(hào)括起的列表(初始化列表)的使用范圍,使其可用于所有的內(nèi)置類型和用戶自定義的類型,使用初始化列表時(shí),可添加等號(hào)(=),也可不添加

1.2. 內(nèi)置類型的列表初始化

int main() { // 內(nèi)置類型變量 int x1 = {10}; int x2{10}; int x3 = 1+2; int x4 = {1+2}; int x5{1+2}; // 數(shù)組 int arr1[5] {1,2,3,4,5}; int arr2[]{1,2,3,4,5}; // 動(dòng)態(tài)數(shù)組,在C++98中不支持 int* arr3 = new int[5]{1,2,3,4,5}; // 標(biāo)準(zhǔn)容器 vector<int> v{1,2,3,4,5}; map<int, int> m{{1,1}, {2,2,},{3,3},{4,4},make_pair(5,5)}; return 0; }

注意:列表初始化可以在{}之前使用等號(hào),其效果與不使用=沒有什么區(qū)別.

1.3. 自定義類型的列表初始化

1.標(biāo)準(zhǔn)庫支持單個(gè)對(duì)象的列表初始化

class Point { public:Point(int x = 0, int y = 0): _x(x), _y(y){} private:int _x;int _y; }; int main() {Pointer p{ 1, 2 };return 0; }

2.多個(gè)對(duì)象的列表初始化

多個(gè)對(duì)象想要支持列表初始化,需給該類(模板類)添加一個(gè)帶有initializer_list類型參數(shù)的構(gòu)造函數(shù)即可。注意:initializer_list是系統(tǒng)自定義的類模板,該類模板中主要有三個(gè)方法:begin()、end()迭代器以及獲取區(qū)間中元素個(gè)數(shù)的方法size()

其底層可以看作是使用數(shù)組暫時(shí)將需要初始化的數(shù)據(jù)存儲(chǔ)起來。

例如:這里簡(jiǎn)單實(shí)現(xiàn)以下vector底層的初始化列表:

#include <initializer_list> template<class T> class Vector { public:Vector(initializer_list<T> l): _capacity(l.size()), _size(0) {_array = new T[_capacity];for(auto e : l)_array[_size++] = e; } Vector<T>& operator=(initializer_list<T> l) {_array = new T[_capacity];size_t i = 0;for (auto e : l)_array[i++] = e;return *this; }private:T* _array;size_t _capacity;size_t _size; };

2. 變量類型推導(dǎo)

2.1. 為什么需要類型推導(dǎo)

在定義變量時(shí),必須先給出變量的實(shí)際類型,編譯器才允許定義,但有些情況下可能不知道需要實(shí)際類型怎么給,或者類型寫起來特別復(fù)雜,比如:

#include <map> #include <string> int main() {short a = 32670;short b = 32670;// c如果給成short,會(huì)造成數(shù)據(jù)丟失,如果能夠讓編譯器根據(jù)a+b的結(jié)果推導(dǎo)c的實(shí)際類型,就不會(huì)存在問題short c = a + b;std::map<std::string, std::string> m{{"apple", "蘋果"}, {"banana","香蕉"}};// 使用迭代器遍歷容器, 迭代器類型太繁瑣std::map<std::string, std::string>::iterator it = m.begin();while(it != m.end()){cout<<it->first<<" "<<it->second<<endl;++it;}return 0; }

C++11中,可以使用auto來根據(jù)變量初始化表達(dá)式類型推導(dǎo)變量的實(shí)際類型,可以給程序的書寫提供許多方便。將程序中c與it的類型換成auto,程序可以通過編譯,而且更加簡(jiǎn)潔。

#include <map> #include <string> int main() {std::map<std::string, std::string> m{{"apple", "蘋果"}, {"banana","香蕉"}};auto it = m.begin();while(it != m.end()){cout<<it->first<<" "<<it->second<<endl;++it;}return 0; }

2.2. decltype類型推導(dǎo)

2.2.1 為什么需要decltype

auto使用的前提是:必須要對(duì)auto聲明的類型進(jìn)行初始化,否則編譯器無法推導(dǎo)出auto的實(shí)際類型。但有時(shí)候可能需要根據(jù)表達(dá)式運(yùn)行完成之后結(jié)果的類型進(jìn)行推導(dǎo),因?yàn)榫幾g期間,代碼不會(huì)運(yùn)行,此時(shí)auto也就無能為力。

template<class T1, class T2> T1 Add(const T1& left, const T2& right) {return left + right; }template<class T1, class T2> auto Add(const T1& left, const T2& right) // 將返回值類型換成auto去自動(dòng)推導(dǎo),這里就會(huì)出錯(cuò) {return left + right; }

如果能用加完之后結(jié)果的實(shí)際類型作為函數(shù)的返回值類型就不會(huì)出錯(cuò),但這需要程序運(yùn)行完才能知道結(jié)果的實(shí)際類型,即RTTI(Run-Time Type Identification 運(yùn)行時(shí)類型識(shí)別)。

C++98中確實(shí)已經(jīng)支持RTTI:typeid只能查看類型不能用其結(jié)果類定義類型dynamic_cast只能應(yīng)用于含有虛函數(shù)的繼承體系中

運(yùn)行時(shí)類型識(shí)別的缺陷是降低程序運(yùn)行的效率。

2.2.2. decltype

decltype是根據(jù)表達(dá)式的實(shí)際類型推演出定義變量時(shí)所用的類型,比如:

1.推演表達(dá)式類型作為變量的定義類型

int main() {int a = 10;int b = 20;// 用decltype推演a+b的實(shí)際類型,作為定義c的類型decltype(a+b) c;cout<<typeid(c).name()<<endl; // typeid只能用作打印出對(duì)象的類型return 0; }

2. 推演函數(shù)返回值的類型

void* func(size_t size) {return malloc(size); } int main() {// 如果沒有帶參數(shù),推導(dǎo)函數(shù)的類型cout << typeid(decltype(func)).name() << endl;// 如果帶參數(shù)列表,推導(dǎo)的是函數(shù)返回值的類型,注意:此處只是推演,不會(huì)執(zhí)行函數(shù)cout << typeid(decltype(func(0))).name() <<endl;return 0; }

3. 對(duì)默認(rèn)成員的控制(default、delete)

在C++中對(duì)于 空類編譯器會(huì)生成一些默認(rèn)的成員函數(shù),比如: 構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、運(yùn)算符重載、析構(gòu)函數(shù)和&和const&的重載、移動(dòng)構(gòu)造、移動(dòng)拷貝構(gòu)造等函數(shù)。如果在類中顯式定義了,編譯器將不會(huì)重新生成默認(rèn)版本。 有時(shí)候這樣的規(guī)則可能被忘記,最常見的是聲明了帶參數(shù)的構(gòu)造函數(shù),必要時(shí)則需要定義不帶參數(shù)的版本以實(shí)例化無參的對(duì)象。而且 有時(shí)編譯器會(huì)生成,有時(shí)又不生成,容易造成混亂,于是C++11讓程序員可以控制是否需要編譯器生成

3.1. 顯式缺省函數(shù)

在C++11中,可以在默認(rèn)函數(shù)定義或者聲明時(shí)加上=default,從而顯式的指示編譯器生成該函數(shù)的默認(rèn)版本,用=default修飾的函數(shù)稱為顯式缺省函數(shù)。

比如看以下代碼:

#include<iostream> #include<string> using namespace std;class person { public://person(){}//person() = default;person(const person& p) //這里由于顯式的創(chuàng)建拷貝構(gòu)造,所以編譯器不會(huì)默認(rèn)生成構(gòu)造函數(shù),因?yàn)榭截悩?gòu)造也是特殊的構(gòu)造函數(shù){_age = p._age;_name = p._name;} private:int _age;string _name; };int main() {person p1; // 由于編譯器沒有生成默認(rèn)構(gòu)造函數(shù),所以這里在定義對(duì)象p1時(shí)會(huì)找不到默認(rèn)的構(gòu)造函數(shù)導(dǎo)致出錯(cuò)person p2 = p1; return 0; }

所以這時(shí),如果不想顯式的寫出構(gòu)造函數(shù),就可以使用default,這樣編譯器就會(huì)認(rèn)為并沒有默認(rèn)構(gòu)造函數(shù),就會(huì)自動(dòng)生成。

person() = default;

3.2. 刪除默認(rèn)函數(shù)

如果能想要限制某些默認(rèn)函數(shù)的生成,在C++98中,是該函數(shù)設(shè)置成private,并且不給定義,這樣只要其他人想要調(diào)用就會(huì)報(bào)錯(cuò)。在C++11中更簡(jiǎn)單,只需在該函數(shù)聲明加上=delete即可,該語法指示編譯器不生成對(duì)應(yīng)函數(shù)的默認(rèn)版本,稱=delete修飾的函數(shù)為刪除函數(shù)

例如:不想讓一個(gè)類對(duì)象進(jìn)行拷貝構(gòu)造

class person { public:person(int age = 10, string name = "edward"):_age(age),_name(name){}person(const person& p) = delete; // C++11做法,使用delete關(guān)鍵字private:int _age;string _name;person(const person& p); // C++98做法:將拷貝構(gòu)造私有,并且只聲明不實(shí)現(xiàn) };int main() {person p1;return 0; }

3.3. final和override

這兩個(gè)關(guān)鍵字也是C++11新增的,但是其實(shí)我們?cè)趯W(xué)習(xí)繼承和多態(tài)的時(shí)候已經(jīng)見過了,這里不再過多描述。

final:修飾類,使該類不能被繼承;修飾虛函數(shù),該虛函數(shù)不能被重寫。

override:檢查派生類虛函數(shù)是否重寫了基類某個(gè)虛函數(shù),如果沒有重寫編譯報(bào)錯(cuò)

4. 右值引用

4.1. 概念

C++98中提出了引用的概念,引用即別名,引用變量與其引用實(shí)體公共同一塊內(nèi)存空間,而引用的底層是通過指針來實(shí)現(xiàn)的,因此使用引用,可以提高程序的可讀性。

為了提高程序運(yùn)行效率,C++11中引入了右值引用,右值引用也是別名,但其只能對(duì)右值引用。

int fun(int n) {return n - 1; }int main() {int x = 1, y = 2;int&& a = 10; // 引用常量int&& b = x + y; // 引用表達(dá)式int&& c = fun(2); // 引用函數(shù)返回值return 0; }

4.2. 右值與左值

左值與右值是C語言中的概念,但C標(biāo)準(zhǔn)并沒有給出嚴(yán)格的區(qū)分方式,一般認(rèn)為:可以放在=左邊的,或者能夠取地址的稱為左值,只能放在=右邊的,或者不能取地址的稱為右值,但是也不一定完全正確。

關(guān)于左值與右值的區(qū)分不是很好區(qū)分,一般認(rèn)為:

  • 普通類型的變量,因?yàn)橛忻?#xff0c;可以取地址,都認(rèn)為是左值。
  • const修飾的常量,不可修改,只讀類型的,理論應(yīng)該按照右值對(duì)待,但因?yàn)槠淇梢匀〉刂?如果只是const類型常量的定義,編譯器不給其開辟空間,如果對(duì)該常量取地址時(shí),編譯器才為其開辟空間),C++11認(rèn)為其是左值。
  • 如果表達(dá)式的運(yùn)行結(jié)果是一個(gè)臨時(shí)變量或者對(duì)象,認(rèn)為是右值。
  • 如果表達(dá)式運(yùn)行結(jié)果或單個(gè)變量是一個(gè)引用則認(rèn)為是左值。
  • 總結(jié):

  • 不能簡(jiǎn)單地通過能否放在=左側(cè)右側(cè)或者取地址來判斷左值或者右值,要根據(jù)表達(dá)式結(jié)果或變量的性質(zhì)判斷,比如上述:c常量
  • 能得到引用的表達(dá)式一定能夠作為引用,否則就用常引用。
  • C++11對(duì)右值進(jìn)行了嚴(yán)格的區(qū)分:
    C語言中的純右值,比如:a+b, 100
    將亡值。比如:表達(dá)式的中間結(jié)果、函數(shù)按照值的方式進(jìn)行返回。

    4.3. 左值引用與右值引用

    那么這里有一個(gè)問題:左值引用能否引用右值,右值引用能否引用左值?

    int main() {int x = 1, y = 2;int& ra = 10; // 左值引用引用右值int& rb = x + y;int&& rra = x; // 右值引用引用左指 int&& rrb = y;return 0; }

    這里通過編譯器可以看到是會(huì)報(bào)錯(cuò)的:

    注意:

    普通引用只能引用左值,不能引用右值,const引用既可引用左值,也可引用右值。C++11中右值引用:只能引用右值,一般情況不能直接引用左值,可以通過move將左值變成右值然后引用

    int main() {int x = 1, y = 2;const int& ra = x + y;int&& rra = std::move(x); // move:將x變成右值cout << ra << endl;cout << rra << endl;return 0; }

    4.4. 左值引用的缺陷

    當(dāng)我們?cè)诤瘮?shù)中使用引用傳傳參時(shí)幾乎是沒有任何問題的,但是當(dāng)函數(shù)中的返回值使用引用返回時(shí)可能就會(huì)出現(xiàn)問題。

    比如:我們使用string的實(shí)現(xiàn)作為例子

    namespace wt {class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷貝構(gòu)造string(const string& s):_str(nullptr), _size(0), _capacity(0){cout << "string(const string& s) -- 深拷貝" << endl;string tmp(s._str);swap(tmp);}string& operator=(const string& s){cout << "string& operator=(string s) -- 深拷貝" << endl;string tmp(s);swap(tmp);return *this;}~string(){//cout << "~string()" << endl;delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//string operator+=(char ch)string& operator+=(char ch){push_back(ch);return *this;}string operator+(char ch){string tmp(*this);push_back(ch);return tmp;}const char* c_str() const{return _str;}private:char* _str;size_t _size;size_t _capacity; // 不包含最后做標(biāo)識(shí)的\0};wt::string to_string(int value){wt::string str;while (value){int val = value % 10;str += ('0' + val);value /= 10;}reverse(str.begin(), str.end());return str;} }// 場(chǎng)景1 // 左值引用做參數(shù),基本完美的解決所有問題 void func1(wt::string s) {}void func2(const wt::string& s) {}// 場(chǎng)景2 // 左值引用做返回值,只能解決部分問題 // wt::string& operator+=(char ch) //解決了 // wt::string operator+(char ch) // 沒有解決,不能使用引用返回

    以前在學(xué)習(xí)拷貝構(gòu)造時(shí)我們學(xué)習(xí)過,當(dāng)上面的operator+這種情況,如果返回值是一個(gè)自定義類型,由于返回的是一個(gè)右值,所以在處理該函數(shù)的作用域之后,該右值會(huì)被立即銷毀。所以在返回之前,會(huì)調(diào)用一次拷貝構(gòu)造將返回值臨時(shí)保存在調(diào)用該函數(shù)的棧幀中,然后再將臨時(shí)值拷貝構(gòu)造給接收該函數(shù)的對(duì)象。(這里編譯器會(huì)優(yōu)化為一次拷貝構(gòu)造)

    這里會(huì)發(fā)現(xiàn):返回值、拷貝構(gòu)造的臨時(shí)對(duì)象、ans每個(gè)對(duì)象創(chuàng)建后都有自己的獨(dú)立的空間,而且每個(gè)空間中的內(nèi)容也完全相同,相當(dāng)于創(chuàng)建了三個(gè)內(nèi)容完全相同的對(duì)象,對(duì)于空間是一種浪費(fèi),程序的效率也會(huì)降低,而且臨時(shí)對(duì)象確實(shí)作用不是很大 。

    4.5. 移動(dòng)語義

    C++11提出了移動(dòng)語義概念,即:將一個(gè)對(duì)象中資源移動(dòng)到另一個(gè)對(duì)象中的方式,可以有效緩解該問題。

    // 移動(dòng)構(gòu)造string(string&& s) //創(chuàng)建一個(gè)空string對(duì)象:_str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 資源轉(zhuǎn)移" << endl;this->swap(s); // 將s內(nèi)部的資源轉(zhuǎn)移給空對(duì)象,由于s是右值后面會(huì)被釋放,所以這里不會(huì)對(duì)它造成影響}// 移動(dòng)賦值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 轉(zhuǎn)移資源" << endl;swap(s);return *this;} int main() {wt::string s1;wt::string s2 = wt::to_string(1234);cout << endl;s1 = wt::to_string(1234);return 0; }

    這里我們使用to_string(1234)函數(shù)的返回值去初始化s2和賦值給s1,如果沒有移動(dòng)構(gòu)造和移動(dòng)賦值,那么肯定是會(huì)去深拷貝的:

    如果有移動(dòng)構(gòu)造和移動(dòng)賦值則不會(huì):

    有了移動(dòng)語義,應(yīng)該慎用move,因?yàn)槿绻麑⒁粋€(gè)左值給move了,那么他內(nèi)部的資源就可能被轉(zhuǎn)移走了,這時(shí)再去使用這個(gè)左值對(duì)象就可能出現(xiàn)問題。

    4.6. 移動(dòng)構(gòu)造和移動(dòng)賦值

    原來C++類中,有6個(gè)默認(rèn)成員函數(shù):

  • 構(gòu)造函數(shù)
  • 析構(gòu)函數(shù)
  • 拷貝構(gòu)造函數(shù)
  • 拷貝賦值重載
  • 取地址重載
  • const 取地址重載
  • 最后重要的是前4個(gè),后兩個(gè)用處不大。默認(rèn)成員函數(shù)就是我們不寫編譯器會(huì)生成一個(gè)默認(rèn)的。

    C++11新增了兩個(gè):移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符重載

    針對(duì)移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符重載有一些需要注意的點(diǎn)如下:

    如果 自己沒有實(shí)現(xiàn)移動(dòng)構(gòu)造函數(shù),且沒有實(shí)現(xiàn)析構(gòu)函數(shù)、拷貝構(gòu)造、拷貝賦值重載中的任意一個(gè)。那么編譯器會(huì)自動(dòng)生成一個(gè)默認(rèn)移動(dòng)構(gòu)造。默認(rèn)生成的移動(dòng)構(gòu)造函數(shù),對(duì)于內(nèi)置類型成員會(huì)執(zhí)行逐成員按字節(jié)拷貝,自定義類型成員,則需要看這個(gè)成員是否實(shí)現(xiàn)移動(dòng)構(gòu)造,如果實(shí)現(xiàn)了就調(diào)用移動(dòng)構(gòu)造,沒有實(shí)現(xiàn)就調(diào)用拷貝構(gòu)造。
    如果 自己沒有實(shí)現(xiàn)移動(dòng)賦值重載函數(shù),且沒有實(shí)現(xiàn)析構(gòu)函數(shù)、拷貝構(gòu)造、考貝賦值重載中的任意一個(gè),那么編譯器會(huì)白動(dòng)生成一個(gè)默認(rèn)移動(dòng)賦值。默認(rèn)生成的移動(dòng)構(gòu)造函數(shù),對(duì)于內(nèi)置類型成員會(huì)執(zhí)行逐成員按字節(jié)拷貝,白定義類型成員,則需要看這個(gè)成員是否實(shí)現(xiàn)移動(dòng)賦值,如果實(shí)現(xiàn)了就調(diào)用移動(dòng)賦值,沒有實(shí)現(xiàn)就調(diào)用拷貝賦值。(默認(rèn)移動(dòng)賦值跟上面移動(dòng)構(gòu)造完全類似)
    如果 你提供了移動(dòng)構(gòu)造或者移動(dòng)賦值,編譯器不會(huì)自動(dòng)提供拷貝構(gòu)造和拷貝賦值

    4.7. 完美轉(zhuǎn)發(fā)

    完美轉(zhuǎn)發(fā)是指在函數(shù)模板中,完全依照模板的參數(shù)的類型,將參數(shù)傳遞給函數(shù)模板中調(diào)用的另外一個(gè)函數(shù)。

    假如有以下場(chǎng)景:

    void Fun(int& x) { cout << "左值引用" << endl; } void Fun(const int& x) { cout << "const 左值引用" << endl; }void Fun(int&& x) { cout << "右值引用" << endl; } void Fun(const int&& x) { cout << "const 右值引用" << endl; } template<typename T> void PerfectForward(T&& t) {Fun(t); }int main() {PerfectForward(10); // 右值int a;PerfectForward(a); // 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b); // const 左值PerfectForward(std::move(b)); // const 右值return 0; }

    根據(jù)上面的代碼產(chǎn)生的結(jié)果我們會(huì)發(fā)現(xiàn),為什么給函數(shù)中傳入的右值,再傳入Fun函數(shù)后全部匹配到了左值引用的函數(shù)?

    模板中的&&不代表右值引用,而是萬能引用,其既能接收左值又能接收右值。
    模板的萬能引用只是提供了能夠接收同時(shí)接收左值引用和右值引用的能力,
    但是引用類型的唯一作用就是限制了接收的類型,后續(xù)使用中都退化成了左值,

    由于傳入的是右值,所以PerfectForward函數(shù)在接收他時(shí)會(huì)創(chuàng)建一塊臨時(shí)的空間保存它,這時(shí)這個(gè)右值就可以被取地址了,所以它的屬性就變成了右值!

    我們希望能夠在傳遞過程中保持它的左值或者右值的屬性, 就需要用我們下面學(xué)習(xí)的完美轉(zhuǎn)發(fā):

    Fun(std::forward<T>(t)); //forward<T> 完美轉(zhuǎn)發(fā):將參數(shù)按照傳遞給轉(zhuǎn)發(fā)函數(shù)的實(shí)際類型轉(zhuǎn)給目標(biāo)函數(shù),而不產(chǎn)生額外的開銷

    所謂完美:函數(shù)模板在向其他函數(shù)傳遞自身形參時(shí),如果相應(yīng)實(shí)參是左值,它就應(yīng)該被轉(zhuǎn)發(fā)為左值;如果相應(yīng)實(shí)參是右值,它就應(yīng)該被轉(zhuǎn)發(fā)為右值

    5. lambda表達(dá)式

    從C語言的函數(shù)指針到C++98的仿函數(shù),在有些時(shí)候使用其實(shí)很不方便,特別是函數(shù)指針,所以C++11中添加了lambda表達(dá)式。

    5.1. lambda表達(dá)式語法

    lambda表達(dá)式書寫格式:[capture-list] (parameters) mutable -> return-type { statement }

    lambda表達(dá)式各部分說明

    [capture-list] : 捕捉列表,該列表總是出現(xiàn)在lambda函數(shù)的開始位置,編譯器根據(jù)[]來判斷接下來的代碼是否為lambda函數(shù)捕捉列表能夠捕捉上下文中的變量供lambda函數(shù)使用

    (parameters):參數(shù)列表。與普通函數(shù)的參數(shù)列表一致,如果不需要參數(shù)傳遞,則可以連同()一起省略

    mutable:默認(rèn)情況下,lambda函數(shù)總是一個(gè)const函數(shù),mutable可以取消其常量性。使用該修飾符時(shí),參數(shù)列表不可省略(即使參數(shù)為空)。

    ->returntype:返回值類型。用追蹤返回類型形式聲明函數(shù)的返回值類型,沒有返回值時(shí)此部分可省略。返回值類型明確情況下,也可省略,由編譯器對(duì)返回類型進(jìn)行推導(dǎo)

    {statement}:函數(shù)體。在該函數(shù)體內(nèi),除了可以使用其參數(shù)外,還可以使用所有捕獲到的變量。

    注意:

    在lambda函數(shù)定義中,參數(shù)列表和返回值類型都是可選部分,而捕捉列表和函數(shù)體可以為空

    因此C++11中最簡(jiǎn)單的lambda函數(shù)為:[]{}; 該lambda函數(shù)不能做任何事情。

    int main() {// 最簡(jiǎn)單的lambda表達(dá)式, 該lambda表達(dá)式?jīng)]有任何意義[]{};// 省略參數(shù)列表和返回值類型,返回值類型由編譯器推導(dǎo)為intint a = 3, b = 4;[=]{return a + 3; };// 省略了返回值類型,無返回值類型auto fun1 = [&](int c){b = a + c; };fun1(10)cout<< a <<" "<<b<<endl;// 各部分都很完善的lambda函數(shù)auto fun2 = [=, &b](int c)->int{return b += a+ c; };cout<<fun2(10)<<endl;// 賦值捕捉xint x = 10;auto add_x = [x](int a) mutable { x *= 2; return a + x; };cout << add_x(10) << endl;return 0; }

    通過上述例子可以看出,lambda表達(dá)式實(shí)際上可以理解為無名函數(shù),該函數(shù)無法直接調(diào)用,如果想要直接調(diào)用,可借助auto將其賦值給一個(gè)變量。

    捕獲列表說明

    捕捉列表描述了上下文中那些數(shù)據(jù)可以被lambda使用,以及使用的方式傳值還是傳引用

    [var]:表示值傳遞方式捕捉變量var
    [=]:表示值傳遞方式捕獲所有父作用域中的變量(包括this)
    [&var]:表示引用傳遞捕捉變量var
    [&]:表示引用傳遞捕捉所有父作用域中的變量(包括this)
    [this]:表示值傳遞方式捕捉當(dāng)前的this指針

    注意:

    a. 父作用域指包含lambda函數(shù)的語句塊

    b. 語法上捕捉列表可由多個(gè)捕捉項(xiàng)組成,并以逗號(hào)分割

    比如:[=, &a, &b]:以引用傳遞的方式捕捉變量a和b,值傳遞方式捕捉其他所有變量 [&,a, this]:值傳遞方式捕捉變量a和this,引用方式捕捉其他變量

    c. 捕捉列表不允許變量重復(fù)傳遞,否則就會(huì)導(dǎo)致編譯錯(cuò)誤。 比如:[=, a]:=已經(jīng)以值傳遞方式捕捉了所有變量,捕捉a重復(fù)

    d. 在塊作用域以外的lambda函數(shù)捕捉列表必須為空

    e. 在塊作用域中的lambda函數(shù)僅能捕捉父作用域中局部變量,捕捉任何非此作用域或者非局部變量都會(huì)導(dǎo)致編譯報(bào)錯(cuò)。

    f. lambda表達(dá)式之間不能相互賦值,即使看起來類型相同

    實(shí)際在底層編譯器對(duì)于lambda表達(dá)式的處理方式,完全就是按照函數(shù)對(duì)象的方式處理的,即:如果定義了一個(gè)lambda表達(dá)式,編譯器會(huì)自動(dòng)生成一個(gè)類,在該類中重載了operator()

    6. 包裝器

    6.1. 為什么需要包裝器

    function包裝器 也叫作適配器。C++中的function本質(zhì)是一個(gè)類模板,也是一個(gè)包裝器。

    • func可能是什么呢?那么func可能是函數(shù)名?函數(shù)指針?函數(shù)對(duì)象(仿函數(shù)對(duì)象)?也有可能
    • 是lamber表達(dá)式對(duì)象?所以這些都是可調(diào)用的類型!
    • 如此豐富的類型,可能會(huì)導(dǎo)致模板的效率低下! 為什么呢?
    template<class F, class T> T useF(F f, T x) {static int count = 0;cout << "count:" << ++count << endl;cout << "count:" << &count << endl;return f(x); }double f(double i) {return i / 2; }struct Functor {double operator()(double d){return d / 3;} };int main() {// 函數(shù)名cout << useF(f, 22.22) << endl;// 函數(shù)對(duì)象cout << useF(Functor(), 33.33) << endl; //匿名對(duì)象// lamber表達(dá)式cout << useF([](double d)->double { return d / 4; }, 44.44) << endl;return 0; }

      • 由于函數(shù)指針、仿函數(shù)、lambda表達(dá)式是不同的類型,因此useF函數(shù)會(huì)被實(shí)例化出三份,三次調(diào)用useF函數(shù)所打印count的地址也是不同的。
      • 但實(shí)際這里根本沒有必要實(shí)例化出三份useF函數(shù),因?yàn)槿握{(diào)用useF函數(shù)時(shí)傳入的可調(diào)用對(duì)象雖然是不同類型的,但這三個(gè)可調(diào)用對(duì)象的返回值和形參類型都是相同的。

    使用包裝器可以解決這里的問題:

    template <class T> function; template <class Ret, class... Args> class function<Ret(Args...)>;

    模板參數(shù)說明

    • Ret :被包裝的可調(diào)用對(duì)象的返回值類型。
    • Args... :被包裝的可調(diào)用對(duì)象的形參類型。

    6.2. 包裝器的使用

    function包裝器可以對(duì)可調(diào)用對(duì)象進(jìn)行包裝,包括函數(shù)指針(函數(shù)名)、仿函數(shù)(函數(shù)對(duì)象)、lambda表達(dá)式、類的成員函數(shù)

    template<class F, class T> T useF(F f, T x) {static int count = 0;cout << "count: " << ++count << endl;cout << "count: " << &count << endl;return f(x); }double f(double i) {return i / 2; }struct Functor {double operator()(double d){return d / 3;} };int main() {//函數(shù)名function<double(double)> func1 = f;cout << useF(func1, 22.22) << endl;//函數(shù)對(duì)象function<double(double)> func2 = Functor();cout << useF(func2, 33.33) << endl;//lambda表達(dá)式function<double(double)> func3 = [](double d)->double {return d / 4; };cout << useF(func3, 44.44) << endl;return 0; }

    用包裝器分別對(duì)著三個(gè)可調(diào)用對(duì)象進(jìn)行包裝,然后再用這三個(gè)包裝后的可調(diào)用對(duì)象來調(diào)用useF函數(shù),這時(shí)就只會(huì)實(shí)例化出一份useF函數(shù)。

    根本原因就是因?yàn)榘b后,這三個(gè)可調(diào)用對(duì)象都是相同的function類型,因此最終只會(huì)實(shí)例化出一份useF函數(shù),該函數(shù)的第一個(gè)模板參數(shù)的類型就是function類型的。

    當(dāng)包裝器包裝類的非靜態(tài)成員函數(shù)時(shí)需要額外注意:

    class Plus { public:static int plusi(int a, int b){return a + b;}double plusd(double a, double b){return a + b;} }; int main() {function<double(Plus, double, double)> func5 = &Plus::plusd; //&不可省略cout << func5(Plus(), 1.1, 2.2) << endl; // 需要傳入類對(duì)象去調(diào)用類中的非靜態(tài)成員函數(shù)return 0; }

    6.3. bind包裝器

    bind也是一種函數(shù)包裝器,也叫做適配器。它可以接受一個(gè)可調(diào)用對(duì)象,生成一個(gè)新的可調(diào)用對(duì)象來“適應(yīng)”原對(duì)象的參數(shù)列表。

    bind函數(shù)模板的原型

    template <class Fn, class... Args> bind(Fn&& fn, Args&&... args);template <class Ret, class Fn, class... Args> bind(Fn&& fn, Args&&... args);
    • fn : 可調(diào)用對(duì)象。
    • args... :要綁定的參數(shù)列表:值或占位符。

    6.3.1. bind包裝器改變參數(shù)位置

    int Plus(int a, int b) {return a - b; }int main() {function<int(int, int)> func = bind(Plus, placeholders::_2, placeholders::_1);// 將參數(shù)1與參數(shù)2交換位置cout << func(1, 2) << endl; //1return 0; }

    綁定時(shí)第一個(gè)參數(shù)傳入函數(shù)指針這個(gè)可調(diào)用對(duì)象,但后續(xù)傳入的要綁定的參數(shù)列表依次是placeholders::2和placeholders::1,表示后續(xù)調(diào)用新生成的可調(diào)用對(duì)象時(shí),傳入的第一個(gè)參數(shù)傳給placeholders::2,傳入的第二個(gè)參數(shù)傳給placeholders::1。

    6.3.2. bind包裝器綁定固定參數(shù)

    int Plus(int a, int b) {return a + b; }int main() {//綁定固定參數(shù)function<int(int)> func = bind(Plus, placeholders::_1, 10);cout << func(2) << endl; //12return 0; }
    • 想把Plus函數(shù)的第二個(gè)參數(shù)固定綁定為10,可以在綁定時(shí)將參數(shù)列表的placeholders::_2設(shè)置為10
    • 此時(shí)調(diào)用綁定后新生成的可調(diào)用對(duì)象時(shí)就只需要傳入一個(gè)參數(shù),它會(huì)將該值與10相加后的結(jié)果進(jìn)行返回

    bind包裝器的意義:

    • 將一個(gè)函數(shù)的某些參數(shù)綁定為固定的值,讓我們?cè)谡{(diào)用時(shí)可以不用傳遞某些參數(shù)。
    • 可以對(duì)函數(shù)參數(shù)的順序進(jìn)行靈活調(diào)整。

    7. thread線程庫

    7.1. thread線程庫函數(shù)介紹

    在C++11之前,涉及到多線程問題,都是和平臺(tái)相關(guān)的,比如windows和linux下各有自己的接口,這使得代碼的可移植性比較差

    C++11中最重要的特性就是對(duì)線程進(jìn)行支持了,使得C++在并行編程時(shí)不需要依賴第三方庫,而且在原子操作中還引入了原子類的概念。

    要使用標(biāo)準(zhǔn)庫中的線程,必須包含< thread >頭文件。

    函數(shù)名

    功能

    thread()

    構(gòu)造一個(gè)線程對(duì)象,沒有關(guān)聯(lián)任何線程函數(shù),即沒有啟動(dòng)任何線程

    thread(fn, args1, args2, ...)

    構(gòu)造一個(gè)線程對(duì)象,并關(guān)聯(lián)線程函數(shù)fn,args1,args2,...為線程函數(shù)的參數(shù)

    get_id()

    獲取線程id

    jionable()

    線程是否還在執(zhí)行,joinable代表的是一個(gè)正在執(zhí)行中的線程。

    jion()

    該函數(shù)調(diào)用后會(huì)阻塞住線程,當(dāng)該線程結(jié)束后,主線程繼續(xù)執(zhí)行

    detach()

    在創(chuàng)建線程對(duì)象后馬上調(diào)用,用于把被創(chuàng)建線程與線程對(duì)象分離開,分離的線程 變?yōu)楹笈_(tái)線程,創(chuàng)建的線程的"死活"就與主線程無關(guān)

    注意:

  • 線程是操作系統(tǒng)中的一個(gè)概念,線程對(duì)象可以關(guān)聯(lián)一個(gè)線程,用來控制線程以及獲取線程的狀態(tài)
  • 當(dāng)創(chuàng)建一個(gè)線程對(duì)象后,沒有提供線程函數(shù),該對(duì)象實(shí)際沒有對(duì)應(yīng)任何線程 。
  • 例如:

    #include<iostream> #include<thread> using namespace std;void func(int n) {cout << this_thread::get_id() << endl; //打印該線程的idfor (int i = 0; i < n; ++i){cout << i << endl;} }int main() {thread t1(func, 10); //創(chuàng)建線程//thread(func, 10).detach(); //創(chuàng)建匿名線程 注意:匿名線程必須在創(chuàng)建時(shí)將線程分離,因?yàn)楹竺鏁?huì)找不到t1.join(); //線程等待// this_thread::sleep_for(std::chrono::seconds(3)); //使當(dāng)前線程休眠return 0; }

    其實(shí)這里線程的創(chuàng)建的方法與前面linux中學(xué)習(xí)的類似,只是C++11中用對(duì)象封裝了,使用起來更加方便了。

    get_id()的返回值類型為id類型,id類型實(shí)際為std::thread命名空間下封裝的一個(gè)類(因?yàn)閃indows和Linux下對(duì)線程id處理的方式不同,C++中為了方便跨平臺(tái)的使用所以這樣處理),該類中包含了一個(gè)結(jié)構(gòu)體:

    // vs下查看 typedef struct { /* thread identifier for Win32 */void *_Hnd; /* Win32 HANDLE */unsigned int _Id; } _Thrd_imp_t;

    當(dāng)創(chuàng)建一個(gè)線程對(duì)象后,并且給線程關(guān)聯(lián)線程函數(shù),該線程就被啟動(dòng),與主線程一起運(yùn)行。線程函數(shù)一般情況下可按照以下三種方式提供:

    函數(shù)指針
    lambda表達(dá)式
    函數(shù)對(duì)象

    例如:

    class add { public:int operator()(int x, int y){return x + y;} };int func(int x, int y) {return x + y; }int main() {int a = 10, b = 20;thread t1(func, a, b); // 函數(shù)指針thread t2([=](int, int)->int {return a + b; }, a, b); // lambda表達(dá)式function<int<int,int>> A = add();thread t3(A,a,b); // 函數(shù)對(duì)象t1.join();t2.join();t3.join();return 0; }

    thread類是防拷貝的,不允許拷貝構(gòu)造以及賦值,但是可以移動(dòng)構(gòu)造和移動(dòng)賦值,即將一個(gè)線程對(duì)象關(guān)聯(lián)線程的狀態(tài)轉(zhuǎn)移給其他線程對(duì)象,轉(zhuǎn)移期間不意向線程的執(zhí)行。

    可以通過jionable()函數(shù)判斷線程是否是有效的,如果是以下任意情況,則線程無效:

    1.采用無參構(gòu)造函數(shù)構(gòu)造的線程對(duì)象
    2.線程對(duì)象的狀態(tài)已經(jīng)轉(zhuǎn)移給其他線程對(duì)象
    3.線程已經(jīng)調(diào)用jion或者detach結(jié)束

    面試題:并發(fā)與并行的區(qū)別?

    并發(fā):

    當(dāng)存在多個(gè)線程時(shí),若系統(tǒng)僅有一個(gè)CPU,則根本不可能真正地同時(shí)進(jìn)行一個(gè)以上的線程,系統(tǒng)只能把CPU的運(yùn)行時(shí)間劃分為若干個(gè)時(shí)間段,再將時(shí)間段分配給各個(gè)線程。在一個(gè)線程在其時(shí)間段執(zhí)行時(shí),其余線程處于掛起狀。這種方式我們稱之為并發(fā)。

    并行:

    若系統(tǒng)擁有一個(gè)以上CPU時(shí),則存在多個(gè)線程時(shí)可并行執(zhí)行。當(dāng)一個(gè)CPU執(zhí)行一個(gè)線程時(shí),另一個(gè)CPU可以執(zhí)行另一個(gè)線程,兩個(gè)線程互不搶占CPU資源,可以同時(shí)進(jìn)行。這種方式我們稱之為并行。

    區(qū)別:

    并發(fā)和并行是即相似又有區(qū)別的兩個(gè)概念, 并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生

    在多道程序環(huán)境下,并發(fā)性是指在一段時(shí)間內(nèi)宏觀上有多個(gè)程序在同時(shí)運(yùn)行,但在單處理機(jī)系統(tǒng)中,每一時(shí)刻卻僅能有一道程序執(zhí)行,故微觀上這些程序只能是分時(shí)地交替執(zhí)行。

    7.2. 線程函數(shù)參數(shù)

    線程函數(shù)的參數(shù)是以值拷貝的方式拷貝到線程棧空間中的,因此:即使線程參數(shù)為引用類型,在線程中修改后也不能修改外部實(shí)參,因?yàn)槠鋵?shí)際引用的是線程棧中的拷貝,而不是外部實(shí)參

    當(dāng)然還有一種方法能夠改變參數(shù)的值,那就是指針:

    注意:如果是類成員函數(shù)作為線程參數(shù)時(shí),必須將this作為線程函數(shù)參數(shù)。

    class A { public:int add(int x, int y){cout << x + y << endl;return x + y;} };int main() {A a;// 傳入順序 線程函數(shù),實(shí)例化類指針,函數(shù)參數(shù)thread t1(&A::add, &a, 10, 20);t1.join();return 0; }

    7.3. lock_guard與unique_lock

    在多線程環(huán)境下,如果想要保證某個(gè)變量的安全性,只要將其設(shè)置成對(duì)應(yīng)的原子類型即可,即高效又不容易出現(xiàn)死鎖問題。但是有些情況下,我們可能需要保證一段代碼的安全性,那么就只能通過鎖的方式來進(jìn)行控制。

    比如兩個(gè)線程同時(shí)對(duì)一個(gè)變量進(jìn)行++操作:

    int x = 0;void add(int n) {for (int i = 0; i < n; ++i){x++;cout << this_thread::get_id() << ":" << x << endl;} }int main() {thread t1(add, 10000);thread t2(add, 10000);t1.join();t2.join();return 0; }

    上面的代碼兩個(gè)線程各自對(duì)x加了10000次,但是從結(jié)果中可以發(fā)現(xiàn)x最后的值只有1992,所以這其中一定出現(xiàn)了線程安全問題。

    所以這里需要進(jìn)行加鎖操作,C++11中也新增了加鎖的庫:

    那么這里問題來了,這里的加鎖應(yīng)該加載for循環(huán)的里面還是外面?

    答案是外面。雖然加載外面看起來兩個(gè)線程就是串行運(yùn)行了,但是針對(duì)這里的實(shí)際問題而言++的操作是非常快的,如果鎖加在循環(huán)里面會(huì)導(dǎo)致兩個(gè)線程頻繁的去競(jìng)爭(zhēng)鎖和釋放鎖,頻繁的去切換上下文,導(dǎo)致對(duì)資源的消耗非常大。

    int x = 0; mutex mtx; void add(int n) {mtx.lock();for (int i = 0; i < n; ++i){//mtx.lock();x++;cout << this_thread::get_id() << ":" << x << endl;//mtx.unlock();}mtx.unlock(); }int main() {thread t1(add, 10000);thread t2(add, 10000);t1.join();t2.join();return 0; }

    7.3.1. Mutex的種類

    上述代碼的缺陷:鎖控制不好時(shí),可能會(huì)造成死鎖,最常見的比如在鎖中間代碼返回,或者在鎖的范圍內(nèi)拋異常。因此:C++11采用RAII的方式對(duì)鎖進(jìn)行了封裝,即lock_guard和unique_lock

    在C++11中,Mutex總共包了四個(gè)互斥量的種類:

    mutex:

    C++11提供的最基本的互斥量,該類的對(duì)象之間不能拷貝,也不能進(jìn)行移動(dòng)。mutex最常用的三個(gè)函數(shù):

    函數(shù)名

    函數(shù)功能

    lock()

    上鎖:鎖住互斥量

    unlock()

    解鎖:釋放對(duì)互斥量的所有權(quán)

    try_lock()

    嘗試鎖住互斥量,如果互斥量被其他線程占有,則當(dāng)前線程也不會(huì)被阻塞

    注意,線程函數(shù)調(diào)用lock()時(shí),可能會(huì)發(fā)生以下三種情況:

    • 如果該互斥量當(dāng)前沒有被鎖住,則調(diào)用線程將該互斥量鎖住,直到調(diào)用 unlock之前,該線程一直擁有該鎖
    • 如果當(dāng)前互斥量被其他線程鎖住,則當(dāng)前的調(diào)用線程被阻塞住
    • 如果當(dāng)前互斥量被當(dāng)前調(diào)用線程鎖住,則會(huì)產(chǎn)生死鎖(deadlock)

    線程函數(shù)調(diào)用try_lock()時(shí),可能會(huì)發(fā)生以下三種情況:

    • 如果當(dāng)前互斥量沒有被其他線程占有,則該線程鎖住互斥量,直到該線程調(diào)用 unlock 釋放互斥量
    • 如果當(dāng)前互斥量被其他線程鎖住,則當(dāng)前調(diào)用線程返回 false,而并不會(huì)被阻塞掉
    • 如果當(dāng)前互斥量被當(dāng)前調(diào)用線程鎖住,則會(huì)產(chǎn)生死鎖(deadlock)

    recursive_mutex :

    允許同一個(gè)線程對(duì)互斥量多次上鎖(即遞歸上鎖),來獲得對(duì)互斥量對(duì)象的多層所有權(quán),釋放互斥量時(shí)需要調(diào)用與該鎖層次深度相同次數(shù)的 unlock(),除此之外,std::recursive_mutex 的特性和std::mutex 大致相同。

    timed_mutex :

    比 std::mutex 多了兩個(gè)成員函數(shù),try_lock_for(),try_lock_until() 。

    try_lock_for()

    接受一個(gè)時(shí)間范圍,表示在這一段時(shí)間范圍之內(nèi)線程如果沒有獲得鎖則被阻塞住(與 std::mutex的 try_lock() 不同,try_lock 如果被調(diào)用時(shí)沒有獲得鎖則直接返回 false),如果在此期間其他線程釋放了鎖,則該線程可以獲得對(duì)互斥量的鎖,如果超時(shí)(即在指定時(shí)間內(nèi)還是沒有獲得鎖),則返回 false。

    try_lock_until()

    接受一個(gè)時(shí)間點(diǎn)作為參數(shù),在指定時(shí)間點(diǎn)未到來之前線程如果沒有獲得鎖則被阻塞住,如果在此期間其他線程釋放了鎖,則該線程可以獲得對(duì)互斥量的鎖,如果超時(shí)(即在指定時(shí)間內(nèi)還是沒有獲得鎖),則返回 false。

    7.3.2. lock_guard

    std::lock_gurad 是 C++11 中定義的模板類。定義如下 :

    template<class _Mutex> class lock_guard { public:// 在構(gòu)造lock_gard時(shí),_Mtx還沒有被上鎖explicit lock_guard(_Mutex& _Mtx): _MyMutex(_Mtx){_MyMutex.lock();}// 在構(gòu)造lock_gard時(shí),_Mtx已經(jīng)被上鎖,此處不需要再上鎖lock_guard(_Mutex& _Mtx, adopt_lock_t): _MyMutex(_Mtx){}~lock_guard() _NOEXCEPT{_MyMutex.unlock();}lock_guard(const lock_guard&) = delete;lock_guard& operator=(const lock_guard&) = delete; private:_Mutex& _MyMutex; };

    lock_guard類模板主要是通過RAII的方式,對(duì)其管理的互斥量進(jìn)行了封裝,在需要加鎖的地方,只需要用上述介紹的任意互斥體實(shí)例化一個(gè)lock_guard,調(diào)用構(gòu)造函數(shù)成功上鎖,出作用域前,lock_guard對(duì)象要被銷毀,調(diào)用析構(gòu)函數(shù)自動(dòng)解鎖,可以有效避免死鎖問題。

    lock_guard的缺陷:太單一,用戶沒有辦法對(duì)該鎖進(jìn)行控制,因此C++11又提供了unique_lock。

    7.3.3. unique_lock

    與lock_gard類似,unique_lock*類模板也是采用RAII的方式對(duì)鎖進(jìn)行了封裝,并且也是以獨(dú)占所有權(quán)的方式管理mutex對(duì)象的上鎖和解鎖操作,即其對(duì)象之間不能發(fā)生拷貝。在構(gòu)造(或移動(dòng)(move)賦值)時(shí),unique_lock 對(duì)象需要傳遞一個(gè) Mutex 對(duì)象作為它的參數(shù),新創(chuàng)建的 unique_lock 對(duì)象負(fù)責(zé)傳入的 Mutex對(duì)象的上鎖和解鎖操作。使用以上類型互斥量實(shí)例化unique_lock的對(duì)象時(shí),自動(dòng)調(diào)用構(gòu)造函數(shù)上鎖,unique_lock對(duì)象銷毀時(shí)自動(dòng)調(diào)用析構(gòu)函數(shù)解鎖,可以很方便的防止死鎖問題

    與lock_guard不同的是,unique_lock更加的靈活,提供了更多的成員函數(shù):

    上鎖/解鎖操作:lock、try_lock、try_lock_for、try_lock_until和unlock

    修改操作:移動(dòng)賦值、交換(swap:與另一個(gè)unique_lock對(duì)象互換所管理的互斥量所有權(quán))、釋放(release:返回它所管理的互斥量對(duì)象的指針,并釋放所有權(quán))

    獲取屬性:owns_lock(返回當(dāng)前對(duì)象是否上了鎖)、operator bool()(與owns_lock()的功能相同)、mutex(返回當(dāng)前unique_lock所管理的互斥量的指針)。

    7.4. 原子性操作庫(atomic)

    多線程最主要的問題是共享數(shù)據(jù)帶來的問題(即線程安全)。如果共享數(shù)據(jù)都是只讀的,那么沒問題,因?yàn)橹蛔x操作不會(huì)影響到數(shù)據(jù),更不會(huì)涉及對(duì)數(shù)據(jù)的修改,所以所有線程都會(huì)獲得同樣的數(shù)據(jù)。但是,當(dāng)一個(gè)或多個(gè)線程要修改共享數(shù)據(jù)時(shí),就會(huì)產(chǎn)生很多潛在的麻煩 。

    所謂原子操作:即不可被中斷的一個(gè)或一系列操作,C++11引入的原子操作類型,使得線程間數(shù)據(jù)的同步變得非常高效 。

    對(duì)于上面的問題:兩個(gè)線程同時(shí)對(duì)一個(gè)變量進(jìn)行++操作,這里就可以用到原子性操作:

    #include<atomic> atomic<int> x = 0; void add(int n) {for (int i = 0; i < n; ++i){x++; // 原子操作cout << this_thread::get_id() << ":" << x << endl;} }int main() {thread t1(add, 10000);thread t2(add, 10000);t1.join();t2.join();return 0; }

    在C++11中,程序員不需要對(duì)原子類型變量進(jìn)行加鎖解鎖操作,線程能夠?qū)υ宇愋妥兞炕コ獾脑L問

    更為普遍的,程序員可以使用atomic類模板,定義出需要的任意原子類型

    atmoic<T> t; // 聲明一個(gè)類型為T的原子類型變量t

    注意:原子類型通常屬于"資源型"數(shù)據(jù),多個(gè)線程只能訪問單個(gè)原子類型的拷貝,因此在C++11中,原子類型只能從其模板參數(shù)中進(jìn)行構(gòu)造,不允許原子類型進(jìn)行拷貝構(gòu)造、移動(dòng)構(gòu)造以及operator=等,為了防止意外,標(biāo)準(zhǔn)庫已經(jīng)將atmoic模板類中的拷貝構(gòu)造、移動(dòng)構(gòu)造、賦值運(yùn)算符重載默認(rèn)刪除掉了。

    #include <atomic> int main() {atomic<int> a1(0);//atomic<int> a2(a1); // 編譯失敗atomic<int> a2(0);//a2 = a1; // 編譯失敗return 0; }

    8. 條件變量(condition_variable)

    在學(xué)習(xí)Linux時(shí)我們學(xué)到過條件變量,在C++11中也增加了條件變量。

    問題:如果實(shí)現(xiàn)一個(gè)線程打印偶數(shù),一個(gè)線程打印奇數(shù),且兩個(gè)線程交替打印?

    如果我們使用前面學(xué)過的加鎖來試一試:

    int main() {int end = 100;int i = 0;mutex mtx;thread t1([end, &i, &mtx] {while (i < end){unique_lock<mutex> lock(mtx);this_thread::sleep_for(std::chrono::milliseconds(100));cout << this_thread::get_id() << "->" << i << endl;++i;}});thread t2([end, &i, &mtx] {while (i < end){unique_lock<mutex> lock(mtx);this_thread::sleep_for(std::chrono::milliseconds(100));cout << this_thread::get_id() << "->" << i << endl;++i;}});t1.join();t2.join();return 0; }

    通過結(jié)果我們可以看到,上面的方法根本不能實(shí)現(xiàn)交替打印奇偶數(shù),甚至一個(gè)線程打印了多次。

    所以這里可以使用互斥鎖+條件變量解決:條件變量可以因?yàn)橐粋€(gè)條件的不滿足而使線程陷入休眠狀態(tài),并且釋放已經(jīng)申請(qǐng)到的鎖,直到條件滿足才會(huì)喚醒線程。

    注意:Predicate是一個(gè)可調(diào)用的對(duì)象或函數(shù),他的結(jié)果會(huì)決定線程是否進(jìn)入等待,具體實(shí)現(xiàn)為下圖所示,若while條件成立,會(huì)去調(diào)用wait函數(shù)。

    這里條件變量停止等待的條件時(shí)pred為真。

    #include<condition_variable> int main() {int end = 100;int i = 0;mutex mtx;condition_variable cv;bool flag = false;//打印偶數(shù)thread t1([end, &i, &mtx,&cv,&flag] {while (i < end){unique_lock<mutex> lock(mtx);// flag=false,返回true,t1不會(huì)等待cv.wait(lock, [&flag] {return !flag; });this_thread::sleep_for(std::chrono::milliseconds(100));cout << this_thread::get_id() << "->" << i << endl;++i;flag = true;cv.notify_one();}});//打印奇數(shù)thread t2([end, &i, &mtx, &cv, &flag] {while (i < end){unique_lock<mutex> lock(mtx);// flag = false,返回false,t2會(huì)等待,如果申請(qǐng)到了鎖也會(huì)釋放cv.wait(lock, [&flag] {return flag; });this_thread::sleep_for(std::chrono::milliseconds(100));cout << this_thread::get_id() << "->" << i << endl;++i;flag = false;cv.notify_one();}});t1.join();t2.join();return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的【C++】C++11 新特性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    国产69精品久久久久9999apgf | 久久电影网站中文字幕 | 亚洲天堂在线观看完整版 | 国产专区精品视频 | 久热电影 | 三级小视频在线观看 | 麻豆高清免费国产一区 | 亚洲精品视频网 | 欧美一级久久久久 | 久久都是精品 | 久久9999久久免费精品国产 | 亚洲精品视频在线播放 | 久久久这里有精品 | av一级片在线观看 | 在线久草视频 | 日韩欧美综合在线视频 | 在线看国产 | 色婷婷午夜 | 久久av伊人 | 亚洲精品tv久久久久久久久久 | 手机看片中文字幕 | 欧美视频日韩视频 | 又色又爽又黄高潮的免费视频 | 免费国产亚洲视频 | 国产a级免费 | 欧美精品在线免费 | 久久国产精品99久久久久 | 久久久性| 国产精品你懂的在线观看 | 色综合天天综合在线视频 | 久久99国产综合精品 | 免费男女羞羞的视频网站中文字幕 | 色综合天天综合网国产成人网 | 超碰免费97| 免费观看一级视频 | 久久久久人人 | 美女网站在线 | 国产一区二区在线免费播放 | 天天综合中文 | 免费在线观看污网站 | 亚洲视频精品 | 欧美日韩二三区 | 国产精品成人一区 | 激情网站免费观看 | 久草在线91 | 中文一二区 | 国外成人在线视频网站 | 99在线热播| 国产精品乱码久久久 | 日韩国产精品一区 | 99久久99视频只有精品 | 国产日韩视频在线观看 | 久久久伦理 | 在线观看中文字幕网站 | 国产视频导航 | 久久美女免费视频 | 色综合久久久久综合 | 91少妇精拍在线播放 | 91麻豆国产福利在线观看 | 色综合久久久网 | 久操视频在线免费看 | 久久天堂网站 | 九九免费在线观看视频 | 四虎影视8848dvd | 国产欧美在线一区 | av成人免费在线观看 | 欧美性色xo影院 | 国产精品成人品 | 天天干天天玩天天操 | 国内小视频在线观看 | 男女免费视频观看 | 我要色综合天天 | 中文字幕高清有码 | 五月综合激情婷婷 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 午夜日b视频 | 999视频网站| 色综合天天综合 | 久久嗨| 97色涩| 正在播放五月婷婷狠狠干 | 精品欧美日韩 | 五月天色网站 | 91在线看片 | 就操操久久| 国产成人精品午夜在线播放 | 欧美性免费 | 日韩久久久久久久久久 | 一区二区视频网站 | 又色又爽又黄 | 亚洲精品白浆高清久久久久久 | 天天色草 | 韩国精品在线观看 | 91新人在线观看 | 欧美ⅹxxxxxx | 一区二区三区在线免费观看 | 97超在线| 在线成人av | 日韩精品国产一区 | 国产精品 日本 | 天天摸夜夜操 | 99在线观看视频 | 成人久久免费 | 亚洲精品乱码久久久久v最新版 | 中日韩三级视频 | 最新av网址大全 | 五月天电影免费在线观看一区 | 丰满少妇在线观看 | 国产精品一区二区三区免费视频 | 国产在线观看一 | 久久艹艹 | 国产亚洲情侣一区二区无 | 99综合影院在线 | 日本中文在线 | 丁香花中文在线免费观看 | 久久久久久免费视频 | 最近的中文字幕大全免费版 | 亚洲高清在线视频 | 日韩高清dvd | 亚洲男男gaygay无套 | 精品一区二区久久久久久久网站 | 黄免费网站 | 精品一二三区 | 九九九九色 | 91av视频播放| 精品国产久 | 天天做日日爱夜夜爽 | 国产高清第一页 | 国产午夜精品视频 | 91插插视频 | 日韩精品久久久久久久电影竹菊 | 免费观看成年人视频 | 在线日韩视频 | 日本电影黄色 | 国产精品青青 | av大片免费在线观看 | www色av| h网站免费在线观看 | 二区三区在线视频 | 色综合亚洲精品激情狠狠 | 开心色婷婷 | 最新在线你懂的 | 免费看国产黄色 | 欧美一级片在线免费观看 | 精品字幕在线 | 久久综合精品国产一区二区三区 | 国产小视频免费在线网址 | 日韩不卡高清视频 | 日韩免费高清在线观看 | 国产美女免费观看 | 狠狠狠操| 欧美一区二视频在线免费观看 | 精品久久久免费 | 久久电影色 | 香蕉久久久久久av成人 | 成人在线视频在线观看 | 国产精品毛片久久蜜 | 日韩av电影中文字幕在线观看 | 久久精品视频网站 | 国产91免费在线 | 久草视频首页 | 丁香六月国产 | 一区二区三区四区在线 | 免费福利片2019潦草影视午夜 | 久久综合色婷婷 | 波多野结衣一区二区三区中文字幕 | 国产亚洲在 | 国产最新视频在线 | 日韩精品五月天 | 国产成人777777 | 国产不卡一二三区 | 久久精品一区二区三区中文字幕 | 国产成人性色生活片 | 一区三区视频 | 91在线一区二区 | 色婷婷中文 | 欧美日韩中文字幕视频 | 中文字幕 国产视频 | 青青草国产免费 | 2023天天干| 香蕉成人在线视频 | 色婷婷啪啪免费在线电影观看 | 亚洲精品大全 | 日韩精品电影在线播放 | 久久tv | 美女一区网站 | 成人精品久久 | 97免费在线观看视频 | 亚洲视频专区在线 | 欧美在线99 | 欧洲精品码一区二区三区免费看 | 婷婷丁香综合 | 日本激情视频中文字幕 | 伊人资源视频在线 | 国产一区麻豆 | 久久久黄视频 | 亚洲日本中文字幕在线观看 | av网站在线免费观看 | 色中色资源站 | 久久免费精品视频 | 欧美一级片免费播放 | 免费看亚洲毛片 | 久久亚洲欧美 | 欧美激情精品久久 | 国产高清视频免费观看 | av在线最新 | 九九久久婷婷 | 免费观看版 | 黄色毛片视频免费观看中文 | 国内精品国产三级国产aⅴ久 | 日韩精品久久久久久 | 中文字幕在线中文 | 91视频三区| 免费观看成人网 | 精品久久久久一区二区国产 | 一本一道久久a久久精品 | 久久观看| 高清免费av在线 | 久久99精品国产麻豆宅宅 | 亚洲一级片在线观看 | 黄毛片在线观看 | 天堂av在线免费 | 欧洲一区二区三区精品 | 国产中出在线观看 | 亚洲国产精品一区二区久久,亚洲午夜 | 欧美激情综合五月色丁香小说 | 天天做综合网 | 久久露脸国产精品 | 欧美另类性| 2018亚洲男人天堂 | 久久伦理视频 | 精品影院一区二区久久久 | 波多野结衣日韩 | 亚洲伊人色 | 五月天丁香亚洲 | 夜夜操天天操 | 在线 欧美 日韩 | 视频国产在线观看18 | 香蕉在线影院 | 在线免费三级 | 国产成人免费精品 | 日韩欧美成 | 欧美一级片在线播放 | 国产精品日韩在线观看 | 午夜三级福利 | 精品国产一区二区三区男人吃奶 | 免费观看国产精品视频 | 国产剧情在线一区 | 在线黄av| 在线导航av | 亚洲v欧美v国产v在线观看 | 国产98色在线 | 日韩 | 日韩特级毛片 | 麻豆视频免费入口 | 成人免费视频在线观看 | 国产在线国偷精品产拍 | 久久老司机精品视频 | 中文在线a√在线 | 成人免费在线播放视频 | 国产在线观看av | 456成人精品影院 | 久久精品久久精品久久精品 | 国产麻豆电影 | 日日干夜夜操视频 | 国产手机在线精品 | 丁香六月婷婷开心婷婷网 | 在线播放 亚洲 | 在线看日韩av | 91九色视频在线 | 亚洲欧美精品在线 | 一级欧美黄 | 在线观看久草 | 婷婷色 亚洲 | 亚洲高清视频在线 | 91电影福利 | 日批视频国产 | 美国人与动物xxxx | 一区二区三区中文字幕在线 | 精品久久久久久亚洲综合网 | 精品久久久久久久久亚洲 | 激情网婷婷 | 99视频在线免费观看 | 在线一级片 | 国产黄色片免费观看 | 欧美在线观看禁18 | 亚洲精品久久久久中文字幕二区 | 91视频在线自拍 | 国产高清综合 | 欧美视频国产视频 | 日本不卡123区 | 狠狠的日 | 在线成人免费电影 | 五月天久久激情 | 永久免费的av电影 | 精品久久久网 | 中文字幕丝袜制服 | 香蕉视频91 | 天天射夜夜爽 | 综合色中文 | 99精品国自产在线 | 国产婷婷vvvv激情久 | 亚洲欧洲一区二区在线观看 | 成人免费在线观看av | 久久激情视频免费观看 | 精品国产一区二区三区男人吃奶 | 精品国产1区2区3区 国产欧美精品在线观看 | 97视频免费在线 | 欧美日韩在线精品 | 亚洲伊人第一页 | 超碰大片 | 九九在线视频 | 欧美日韩精品在线视频 | 国产99久久精品 | 国产拍揄自揄精品视频麻豆 | 日韩免费网站 | 一区二区精| 成人一级片视频 | 亚洲一区天堂 | 在线观看成人福利 | 射久久| 久久在线影院 | 日韩成人av在线 | 国产精品在线看 | 9999在线观看 | 亚洲免费一级电影 | 色婷婷啪啪免费在线电影观看 | 免费人成网ww44kk44 | 亚洲第二色 | 91大神dom调教在线观看 | 午夜精品一区二区三区免费视频 | 最新av在线播放 | 国产精品久久久久久高潮 | 亚洲精品在线观 | 99久久99视频 | 精品国产一区二区三区四区在线观看 | 91久久久久久久一区二区 | 天堂中文在线播放 | 中文字幕在线日本 | 99热最新 | 日韩欧美在线观看一区二区 | 久久香蕉影视 | 午夜免费电影院 | 国产一二区精品 | 免费黄a| 久久人人爽人人爽人人 | 在线观看黄色大片 | 91麻豆精品一区二区三区 | 亚洲第一区在线观看 | 在线观看黄色免费视频 | 久久99精品久久久久蜜臀 | 手机av电影在线观看 | 精品国产乱码一区二区三区在线 | 黄色三级免费网址 | 日本爱爱免费 | 日韩精品视频免费专区在线播放 | 91漂亮少妇露脸在线播放 | 天天操综合| 91精品免费视频 | 国产精品入口a级 | 在线国产精品视频 | av超碰在线 | 中文字幕 国产视频 | www.色的 | 99久久精品免费 | 黄色网址中文字幕 | 久久综合干 | 色婷婷一| 国产综合久久 | 精品亚洲欧美一区 | 久久久久久久久久久综合 | 精品在线视频播放 | 国产精品一区二区免费看 | 2024国产精品视频 | 丝袜制服综合网 | 亚洲国产精品免费 | 这里只有精品视频在线观看 | 一级一级一片免费 | 亚洲有 在线 | 欧美国产日韩中文 | 国内丰满少妇猛烈精品播放 | 国产精品久久久一区二区三区网站 | 91夫妻视频 | 日本公乱妇视频 | .国产精品成人自产拍在线观看6 | 亚洲另类xxxx| 久草在线高清视频 | 97在线观看免费 | 激情婷婷久久 | 韩日成人av | 久久999精品 | 一区视频在线 | 亚洲精品伦理在线 | 精品国产成人av | 成人中文字幕+乱码+中文字幕 | 在线观看国产中文字幕 | av中文字幕在线观看网站 | av在线永久免费观看 | 欧美做受高潮 | av中文字幕免费在线观看 | 中文字幕在线观看视频免费 | 99精品免费久久久久久久久 | 狠狠狠狠狠狠狠狠干 | 久久久免费在线观看 | 成人免费xxxxxx视频 | 亚洲美女免费视频 | 色偷偷人人澡久久超碰69 | 麻豆国产精品视频 | 夜夜躁日日躁狠狠久久88av | 久久久久国产成人免费精品免费 | 最近日韩中文字幕中文 | 成人久久亚洲 | 99视频国产精品 | 麻豆传媒视频观看 | 国产亚洲精品久久久久久移动网络 | 欧美日韩久久不卡 | 欧美黄色免费 | 国产丝袜 | 日韩一区在线播放 | 成人在线免费小视频 | 欧美一级免费高清 | 久久精品国产亚洲aⅴ | 国产美女精品视频 | 天天操天天色综合 | 天天干,夜夜操 | 免费观看福利视频 | www99精品| 日本少妇久久久 | 中文字幕亚洲不卡 | 婷婷色中文网 | 成人av免费看 | 狠狠操天天操 | 国产精品亚洲视频 | 又色又爽又激情的59视频 | 亚洲视频 视频在线 | 91麻豆国产福利在线观看 | 免费av高清| 成人免费在线播放 | 伊人电影在线观看 | 国产高清免费观看 | 国产精品美女久久久久久久网站 | 狠狠狠色丁香综合久久天下网 | 又爽又黄在线观看 | 久久综合九色综合欧美狠狠 | 免费亚洲精品视频 | 黄污视频网站 | 亚洲黄色片在线 | 玖玖色在线观看 | 最新日韩在线观看视频 | 六月婷色 | 日本中出在线观看 | 激情视频免费在线 | 美女久久一区 | 黄p在线播放 | 久久久综合香蕉尹人综合网 | 在线免费观看黄色 | 成人小电影在线看 | 成人avav| 五月天.com | 在线成人观看 | 激情深爱| 亚洲精欧美一区二区精品 | 国产一级在线看 | 日韩在线观看av | 三日本三级少妇三级99 | 亚洲国产成人久久 | 婷婷av在线| 亚洲激情在线 | 成人小视频免费在线观看 | 欧洲高潮三级做爰 | 激情综合网婷婷 | 三级大片网站 | 99国产视频在线 | 人人爱夜夜操 | 色老板在线| 国产一区二区三区高清播放 | 美国av大片 | 国内精品免费久久影院 | 人人爱爱| 一区二区三区动漫 | 麻豆久久一区二区 | 91精品国产乱码久久 | 亚洲欧洲一区二区在线观看 | 欧美国产精品一区二区 | 中文字幕免费在线看 | 国产精品亚 | 国产精品久久三 | 蜜臀久久99静品久久久久久 | 亚洲国产小视频在线观看 | 福利视频一二区 | 丁香六月婷婷综合 | 毛片.com| 在线观看香蕉视频 | 欧美网址在线观看 | 天天干天天操天天拍 | 美女精品久久久 | 天天操夜操 | 又爽又黄又刺激的视频 | 色婷婷精品大在线视频 | 一区二区三区在线影院 | 午夜av日韩 | 欧美一区二区日韩一区二区 | 黄毛片在线观看 | 久久在线看 | 黄色毛片观看 | 最新中文字幕视频 | av网站有哪些 | 亚洲精品久久久久中文字幕m男 | 欧美日本中文字幕 | 色网站中文字幕 | 97精品国产97久久久久久粉红 | 欧美亚洲成人xxx | 国产小视频在线播放 | 婷婷视频在线播放 | 97视频久久久 | 国产精品18久久久久白浆 | 激情综合网五月婷婷 | 免费观看黄色av | 99精品视频网站 | 91亚洲国产成人 | 丁香激情婷婷 | 欧美精品你懂的 | 香蕉在线观看视频 | 亚洲成人av在线播放 | 欧美日韩激情视频8区 | 欧美激情精品久久久 | 99热这里只有精品免费 | 久久不卡电影 | 欧美日韩免费观看一区二区三区 | 日韩精品久久久免费观看夜色 | 久久高清av | 成人欧美一区二区三区在线观看 | 中文字幕123区 | 色综合久久久久久久久五月 | 91在线色 | 亚洲国产三级在线观看 | 夜夜躁日日躁狠狠久久88av | 视频在线观看日韩 | 狠狠色丁香久久婷婷综合丁香 | 久久99网站 | 久久久久激情 | www.91av在线 | 国产不卡一二三区 | 亚洲人人av | 五月婷婷综合在线 | 精品国产一区二区三区蜜臀 | 久久久国内精品 | 欧美激情va永久在线播放 | av免费在线观 | 在线国产日韩 | 中文字幕精品一区 | 国产中的精品av小宝探花 | 在线涩涩 | 久久久精品影视 | 色综合国产 | 高潮毛片无遮挡高清免费 | 国产成人精品亚洲日本在线观看 | 日韩二区三区在线观看 | 在线观看免费一级片 | 日韩一区二区三区在线看 | 日韩成人精品一区二区三区 | 欧美一级片在线观看视频 | 国产高清中文字幕 | 播五月综合 | 国产男女爽爽爽免费视频 | www.精选视频.com | 色中色资源站 | 亚洲在线观看av | 天天爽天天搞 | 国产精品久久久久久久久久久久午 | 久久精品综合视频 | 国产成人资源 | 九九九热精品免费视频观看 | 国产精品第一页在线观看 | 色橹橹欧美在线观看视频高清 | 伊人久久电影网 | 天天操天 | 97手机电影网 | 手机成人av在线 | 麻豆传媒视频在线播放 | 天天玩天天操天天射 | 激情五月在线视频 | 麻豆91在线| 中文在线中文a | 中文字幕韩在线第一页 | 欧美 日韩 国产 成人 在线 | av导航福利| 国产精品一区在线观看 | 欧美aaa一级 | 国语精品免费视频 | 亚洲无吗视频在线 | 日韩精品一区二 | 亚洲精品免费在线 | 美女免费视频网站 | 久久久99国产精品免费 | 欧美中文字幕第一页 | 精品福利av | 久久婷婷五月综合色丁香 | 色综合久久五月 | 国产涩涩网站 | 成人a v视频 | 亚洲专区在线播放 | 91在线入口 | 色综合久久88色综合天天 | 怡红院av久久久久久久 | 五月天久久激情 | 中文字幕在线播放av | 一区二区三区免费在线播放 | 久久激五月天综合精品 | 久久不卡视频 | 成人免费在线电影 | 一区二区三区高清在线观看 | 久久成人综合视频 | 亚欧日韩av | 天天综合导航 | 亚洲国产中文字幕在线观看 | 免费视频18| 黄色电影网站在线观看 | 久草在线免费看视频 | 黄色三级免费观看 | 日韩av在线免费看 | 国产区在线视频 | 免费看的黄网站软件 | 婷婷国产在线观看 | av黄免费看 | 人人草在线视频 | 亚洲精品字幕在线 | 天天操夜夜操 | 成人久久综合 | 国产资源在线播放 | 狠狠综合久久av | 亚洲欧美日韩精品久久奇米一区 | 丁香六月婷婷综合 | 日本久久久久久 | 久久精品aaa | 午夜国产成人 | 69国产成人综合久久精品欧美 | 欧美一区三区四区 | 韩国精品福利一区二区三区 | 国产精品初高中精品久久 | 日本最新高清不卡中文字幕 | 五月婷婷在线视频观看 | 狠狠狠色丁香婷婷综合久久五月 | 国色天香av| 91网免费看| 91高清免费看 | 美女黄视频免费看 | 中文字幕有码在线 | 久久亚洲精品国产亚洲老地址 | 中文字幕视频在线播放 | 在线成人免费 | 中文字幕在线网址 | 国产高清一 | 在线免费看黄色 | 四虎影视av | 久99久精品视频免费观看 | 成人黄色资源 | 国产亚州精品视频 | 久久精国产 | 日韩中文免费视频 | 中文字幕精品三级久久久 | 国产一级免费在线 | 欧美午夜视频在线 | 在线观看国产中文字幕 | 亚洲综合色婷婷 | 激情视频在线观看网址 | 四虎影视成人永久免费观看视频 | 欧美一区二区在线刺激视频 | av 一区二区三区 | 亚洲电影成人 | 人人搞人人干 | 久久久精品视频成人 | 欧美日韩精品在线一区二区 | 在线电影91 | 不卡的av在线播放 | 一区二区视频电影在线观看 | 黄色成人av | 综合色影院 | 国产黄色一级片 | 国产无套一区二区三区久久 | 激情综合网在线观看 | 91精品国产乱码久久 | 精品主播网红福利资源观看 | 色九色 | 国产精品久久久久久久久软件 | www.久久com| 麻豆国产网站 | 国产精品免费不卡 | 99精品乱码国产在线观看 | 婷婷在线五月 | 欧美日韩视频 | 8x成人免费视频 | 在线观看911视频 | 亚洲精品国产品国语在线 | 久久久国产99久久国产一 | 国产黄色免费看 | 成人免费看黄 | 国产视频一 | 亚洲激情精品 | 免费在线观看视频一区 | 黄色一区二区在线观看 | 九九av| 免费看色的网站 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产视频在线观看一区 | 精品久久久久久久久久久久久久久久久久 | 深爱婷婷激情 | 91av片| 99热高清| 久久久毛片 | 天天操比 | 亚洲视频 视频在线 | 久久精品视频在线免费观看 | 精品亚洲一区二区 | 亚洲丁香日韩 | 成人av片免费观看app下载 | 天天曰天天干 | 亚洲人天堂 | 精品免费久久久久 | 狠狠综合久久av | 99精品国产高清在线观看 | 麻豆视频免费看 | 日韩高清在线一区二区 | 国模精品在线 | 97av精品| 午夜av片| 丝袜少妇在线 | 乱男乱女www7788 | 天天干,天天操,天天射 | 中文免费观看 | 国产一二三四在线观看视频 | 国产精品美女毛片真酒店 | 欧美日韩在线播放 | 欧美综合色在线图区 | 日韩中文在线观看 | 亚洲国产精品一区二区久久,亚洲午夜 | 99国产在线观看 | 精油按摩av | 亚洲激情小视频 | 操操操影院 | 免费久久视频 | 色94色欧美| 日韩一二三 | 国产亲近乱来精品 | 99婷婷狠狠成为人免费视频 | 国产精品久久久久久久久久新婚 | 久久久精品二区 | 在线亚洲激情 | 亚洲成人精品 | 成人av在线资源 | 成人羞羞视频在线观看免费 | 中文字幕欲求不满 | 色在线中文字幕 | 四虎永久网站 | 成人av播放 | 久久免费视频这里只有精品 | 国产精品专区h在线观看 | 蜜臀av夜夜澡人人爽人人桃色 | 五月婷婷开心中文字幕 | 亚洲国产精品久久久久久 | 婷婷久久久久 | 免费看一级片 | 欧美 激情 国产 91 在线 | 免费在线观看日韩视频 | 天天综合网久久综合网 | 麻豆视频免费在线 | 日韩久久精品一区二区三区下载 | 久久精品国亚洲 | 亚洲最新视频在线播放 | 久久理论电影网 | 91精品秘密在线观看 | 国产福利久久 | 久久婷婷精品视频 | 中文字幕在线观看三区 | 丁香婷婷射 | 黄色aaa毛片 | 东方av免费在线观看 | 日日干激情五月 | 久久电影中文字幕视频 | 天天操天天色天天射 | 超碰免费av | 亚洲永久av| 久久久精品国产一区二区电影四季 | 欧美日韩亚洲精品在线 | 中文字幕一区三区 | 一级特黄aaa大片在线观看 | av在线小说| 欧美精品在线免费 | av一级片在线观看 | av成人免费在线观看 | 最近中文字幕免费 | 91久久久久久久一区二区 | 久久五月网 | 中文字幕精品一区久久久久 | 久草视频免费在线播放 | 99热在| av日韩精品 | 日韩天堂在线观看 | 亚洲免费在线视频 | 欧美国产日韩一区二区三区 | 国产黄色大片免费看 | 成人久久18免费网站麻豆 | 亚洲精品黄色在线观看 | 色综合色综合色综合 | 久久国产精品影片 | 中文字幕在线观看视频网站 | 不卡的av在线| 欧美日韩视频在线观看一区二区 | 91丨九色丨蝌蚪丨老版 | 国产精品一区在线播放 | 国产黄av| 欧美激情一区不卡 | 免费韩国av | 精品久久久久国产 | 免费成人在线观看 | 国产精品网红直播 | 精品国产伦一区二区三区 | 韩日三级在线 | 成人免费在线视频 | 伊甸园永久入口www 99热 精品在线 | 九九热免费在线视频 | 久久成人欧美 | 99久热在线精品视频观看 | www.国产在线 | 久久婷婷一区二区三区 | 综合亚洲视频 | 久久高清片 | 日韩久久精品 | 久草在线一免费新视频 | www激情久久 | 免费看污污视频的网站 | 玖玖综合网 | 人人澡人人爽 | www.狠狠操.com| 美女视频又黄又免费 | 国产精品久久久久久久久软件 | 日韩精品久久久久久 | 午夜美女影院 | 中文字幕亚洲国产 | 在线a亚洲视频播放在线观看 | 综合中文字幕 | 九月婷婷综合网 | 日韩超碰 | 天天干,狠狠干 | av高清免费| 中文字幕精品www乱入免费视频 | 免费a网址| 亚洲va欧美va人人爽春色影视 | 色综合天天狠天天透天天伊人 | 伊人五月天.com | 色欧美成人精品a∨在线观看 | 国产三级视频在线 | 中文字幕有码在线 | 精品一区91| 国产精品久久久久久电影 | 日韩乱码在线 | 久久久久久久久毛片精品 | 午夜少妇一区二区三区 | 久草香蕉在线视频 | 亚洲禁18久人片 | 亚洲观看黄色网 | 九九免费视频 | 中文字幕 在线 一 二 | 91中文字幕视频 | 91一区在线观看 | 伊人婷婷在线 | 欧美整片sss| 免费激情网 | 欧美一级淫片videoshd | 日韩最新中文字幕 | 日韩成人在线一区二区 | 亚洲午夜精品久久久 | 激情久久五月天 | 亚洲高清网站 | 精品毛片一区二区免费看 | 精品一区二区三区香蕉蜜桃 | 五月激情久久久 | 啪啪资源 | 亚洲精品h | 免费看黄视频 | 一级α片| 韩国在线视频一区 | 97高清视频| 中文字幕亚洲精品日韩 | 久久久久久久综合色一本 | 美女久久 | 国产精品久久久久久久久久久杏吧 | 久久精品香蕉视频 | 欧美美女视频在线观看 | 久久久久久久久电影 | 免费看片色 | 91精品国产福利在线观看 | 99亚洲精品 | 黄色小说在线免费观看 | av在线收看 | 国产精品热 | 日韩黄色在线观看 | 在线黄色观看 | 麻豆成人小视频 | 特级毛片爽www免费版 | 国产不卡精品 | 色天天综合网 | 亚洲欧美成人在线 | 99九九视频 | 五月婷婷久久丁香 | 国产伦精品一区二区三区无广告 | 亚洲精品99久久久久中文字幕 | 亚洲黄色一级电影 | 五月婷婷色 | 999久久精品 | 国产成人av免费在线观看 | 亚洲一区免费在线 | 久久情侣偷拍 | 五月婷婷激情综合网 | 99在线热播精品免费 | 久久av免费 | jizz18欧美18 | 欧美精品久久久久久久久久久 | 精品国产一区二区三区在线观看 | 韩国在线一区 | 天天操 夜夜操 | www.色五月| 91av视频观看 | 亚洲成人一二三 | 在线视频一二区 | 成人小视频在线免费观看 | 精壮的侍卫呻吟h | 国产精品久久久久永久免费看 | 91女人18片女毛片60分钟 | 成年人国产在线观看 | 91av国产视频 | 日批视频在线观看免费 | 在线观看av小说 | 欧美资源在线观看 | 日韩在线播放视频 | 中文字幕影片免费在线观看 | 国产成人一区二区三区电影 | 美女久久网站 | 日韩欧美成人网 | 99日精品 | 亚洲第一色 | 五月天综合激情网 | 91免费高清 | 精品视频国产一区 | 91人人澡人人爽 | 中文字幕亚洲精品在线观看 | 国产专区在线看 | 国产高清在线免费视频 | 中文国产在线观看 | 婷婷视频导航 | av黄色免费看 | 日本中文字幕在线看 | 国内精品久久久久影院男同志 | 99久久精品免费看国产 | 天天操网址| 91视频91蝌蚪 | 亚洲狠狠婷婷综合久久久 | 国产精品99久久久精品 | 在线观看视频一区二区 | 日韩精品免费在线 | 国产丝袜高跟 | 六月婷婷久香在线视频 | 毛片网站免费 | 久久嗨| 国产福利精品一区二区 | 91久久偷偷做嫩草影院 | 91精品视频在线观看免费 | 亚洲男男gⅴgay双龙 | 亚洲成人精品av | 人人看人人做人人澡 | 麻豆视频在线 | av免费在线观看网站 | 日韩亚洲在线视频 | 国产视频中文字幕在线观看 | 三上悠亚一区二区在线观看 | 久久99免费观看 | 99在线看| 成人av中文字幕 | 亚洲有 在线 | 在线视频 区 | 久久短视频 | 蜜臀aⅴ国产精品久久久国产 | 青春草免费视频 | av免费观看高清 | 天天综合导航 | 成人黄色小说在线观看 | 人人干,人人爽 | 天天插伊人 | 中文字幕免费一区二区 | 黄色软件视频网站 | 欧美精品在线观看免费 | 久久久久久草 | 日韩中文字幕在线观看 | 人人爽人人爽人人爽学生一级 | 人人舔人人 | 在线亚洲人成电影网站色www | 免费视频99| 亚洲精品玖玖玖av在线看 | 69国产成人综合久久精品欧美 |