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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 智能指针_详解 C++ 11 中的智能指针

發布時間:2024/9/27 c/c++ 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 智能指针_详解 C++ 11 中的智能指针 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C/C++ 語言最為人所詬病的特性之一就是存在內存泄露問題,因此后來的大多數語言都提供了內置內存分配與釋放功能,有的甚至干脆對語言的使用者屏蔽了內存指針這一概念。這里不置貶褒,手動分配內存與手動釋放內存有利也有弊,自動分配內存和自動釋放內存亦如此,這是兩種不同的設計哲學。有人認為,內存如此重要的東西怎么能放心交給用戶去管理呢?而另外一些人則認為,內存如此重要的東西怎么能放心交給系統去管理呢?在 C/C++ 語言中,內存泄露的問題一直困擾著廣大的開發者,因此各類庫和工具的一直在努力嘗試各種方法去檢測和避免內存泄露,如 boost,智能指針技術應運而生。

C++ 98/03 的嘗試——std::auto_ptr

在 2019 年討論?std::auto_ptr?不免有點讓人懷疑是不是有點過時了,確實如此,隨著 C++11 標準的出現(最新標準是 C++20),std::auto_ptr?已經被徹底廢棄了,取而代之是?std::unique_ptr。然而,我之所以還向你介紹一下?std::auto_ptr?的用法以及它的設計不足之處是想讓你了解 C++ 語言中智能指針的發展過程,一項技術如果我們了解它過去的樣子和發展的軌跡,我們就能更好地掌握它,不是嗎?

std::auto_ptr?的基本用法如下代碼所示:

#include?

int?main(){
????//初始化方式1
????std::auto_ptr<int>?sp1(new?int(8));
????//初始化方式2
????std::auto_ptr<int>?sp2;
????sp2.reset(new?int(8));

????return?0;
}

智能指針對象?sp1?和?sp2?均持有一個在堆上分配 int 對象,其值均是 8,這兩塊堆內存均可以在?sp1?和?sp2?釋放時得到釋放。這是?std::auto_ptr?的基本用法。

sp 是 smart pointer(智能指針)的簡寫。

std::auto_ptr?真正讓人容易誤用的地方是其不常用的復制語義,即當復制一個?std::auto_ptr?對象時(拷貝復制或 operator = 復制),原對象所持有的堆內存對象也會轉移給復制出來的對象。示例代碼如下:

#include?
#include?

int?main(){
????//測試拷貝構造
????std::auto_ptr<int>?sp1(new?int(8));
????std::auto_ptr<int>?sp2(sp1);
????if?(sp1.get()?!=?NULL)
????{
????????std::cout?<"sp1?is?not?empty."?<std::endl;
????}
????else
????{
????????std::cout?<"sp1?is?empty."?<std::endl;
????}

????if?(sp2.get()?!=?NULL)
????{
????????std::cout?<"sp2?is?not?empty."?<std::endl;
????}
????else
????{
????????std::cout?<"sp2?is?empty."?<std::endl;
????}

????//測試賦值構造
????std::auto_ptr<int>?sp3(new?int(8));
????std::auto_ptr<int>?sp4 = sp3;;
????if?(sp3.get()?!=?NULL)
????{
????????std::cout?<"sp3?is?not?empty."?<std::endl;
????}
????else
????{
????????std::cout?<"sp3?is?empty."?<std::endl;
????}

????if?(sp4.get()?!=?NULL)
????{
????????std::cout?<"sp4?is?not?empty."?<std::endl;
????}
????else
????{
????????std::cout?<"sp4?is?empty."?<std::endl;
????}

????return?0;
}

上述代碼中分別利用拷貝構造(sp1 => sp2)和 賦值構造(sp3 => sp4)來創建新的 std::auto_ptr 對象,因此 sp1 持有的堆對象被轉移給 sp2,sp3 持有的堆對象被轉移給 sp4。我們得到程序執行結果如下:

[root@iZ238vnojlyZ?testx]#?g++?-g?-o?test_auto_ptr?test_auto_ptr.cpp
[root@iZ238vnojlyZ?testx]#?./test_auto_ptr?
sp1?is?empty.
sp2?is?not?empty.
sp3?is?empty.
sp4?is?not?empty.

由于?std::auto_ptr?這種不常用的復制語義,我們應該避免在 stl 容器中使用?std::auto_ptr,例如我們絕不應該寫出如下代碼:

std::vector<std::auto_ptr<int>>?myvectors;

當用算法對容器操作的時候(如最常見的容器元素遍歷),很難避免不對容器中的元素實現賦值傳遞,這樣便會使容器中多個元素被置為空指針,這不是我們想看到的,會造成很多意想不到的錯誤。

以史為鑒,作為?std::auto_ptr?的替代者?std::unique_ptr?吸取了這個經驗教訓。下文會來詳細介紹。

正因為?std::auto_ptr?的設計存在如此重大缺陷,C++11 標準在充分借鑒和吸收了 boost 庫中智能指針的設計思想,引入了三種類型的智能指針,即?std::unique_ptrstd::shared_ptr?和?std::weak_ptr

boost 還有 scoped_ptr,C++11 并沒有全部照搬,而是選擇了三個最實用的指針類型。在 C++11 中可以通過 std::unique_ptr 達到與 boost::scoped_ptr 一樣的效果。

所有的智能指針類(包括 std::unique_ptr)均包含于頭文件??中。

正因為存在上述設計上的缺陷,在 C++11及后續語言規范中 std::auto_ptr 已經被廢棄,你的代碼不應該再使用它。

std::unique_ptr

std::unique_ptr?對其持有的堆內存具有唯一擁有權,也就是說引用計數永遠是 1,std::unique_ptr?對象銷毀時會釋放其持有的堆內存。可以使用以下方式初始化一個?std::unique_ptr?對象:

//初始化方式1
std::unique_ptr<int>?sp1(new?int(123));

//初始化方式2
std::unique_ptr<int>?sp2;
sp2.reset(new?int(123));

//初始化方式3
std::unique_ptr<int>?sp3?=?std::make_unique<int>(123);

你應該盡量使用初始化方式 3 的方式去創建一個?std::unique_ptr?而不是方式 1 和 2,因為形式 3 更安全,原因 Scott Meyers 在其《Effective Modern C++》中已經解釋過了,有興趣的讀者可以閱讀此書相關章節。

令很多人對 C++11 規范不滿的地方是,C++11 新增了 std::make_shared() 方法創建一個 std::shared_ptr 對象,卻沒有提供相應的 std::make_unique() 方法創建一個 std::unique_ptr 對象,這個方法直到 C++14 才被添加進來。當然,在 C++11 中你很容易實現出這樣一個方法來:

template<typename?T,?typename...?Ts>
std::unique_ptr?make_unique(Ts&&?...params)
{return?std::unique_ptr(new?T(std::forward(params)...));
}

鑒于?std::auto_ptr?的前車之鑒,std::unique_ptr?禁止復制語義,為了達到這個效果,std::unique_ptr?類的拷貝構造函數和賦值運算符(operator =)被標記為?delete

template?<class?T>class?unique_ptr
{
????//省略其他代碼...

????//拷貝構造函數和賦值運算符被標記為delete
????unique_ptr(const?unique_ptr&)?=?delete;
????unique_ptr&?operator=(const?unique_ptr&)?=?delete;
};

因此,下列代碼是無法通過編譯的:

std::unique_ptr<int>?sp1(std::make_unique<int>(123));;

//以下代碼無法通過編譯
//std::unique_ptr?sp2(sp1);
std::unique_ptr<int>?sp3;
//以下代碼無法通過編譯
//sp3?=?sp1;

禁止復制語義也存在特例,即可以通過一個函數返回一個 std::unique_ptr:

#include?

std::unique_ptr<int>?func(int?val)
{
????std::unique_ptr<int>?up(new?int(val));
????return?up;
}

int?main(){
????std::unique_ptr<int>?sp1?=?func(123);

????return?0;
}

上述代碼從 func 函數中得到一個?std::unique_ptr?對象,然后返回給 sp1。

既然?std::unique_ptr?不能復制,那么如何將一個?std::unique_ptr?對象持有的堆內存轉移給另外一個呢?答案是使用移動構造,示例代碼如下:

#include?

int?main(){
????std::unique_ptr<int>?sp1(std::make_unique<int>(123));

????std::unique_ptr<int>?sp2(std::move(sp1));

????std::unique_ptr<int>?sp3;
????sp3?=?std::move(sp2);

????return?0;
}

以上代碼利用 std::move 將 sp1 持有的堆內存(值為 123)轉移給 sp2,再把 sp2 轉移給 sp3。最后,sp1 和 sp2 不再持有堆內存的引用,變成一個空的智能指針對象。并不是所有的對象的 std::move 操作都有意義,只有實現了移動構造函數(Move Constructor)或移動賦值運算符(operator =)的類才行,而?std::unique_ptr?正好實現了這二者,以下是實現偽碼:

template<typename?T,?typename?Deletor>
class?unique_ptr
{
????//其他函數省略...
public:
????unique_ptr(unique_ptr&&?rhs)
????{
????????this->m_pT?=?rhs.m_pT;
????????//源對象釋放
????????rhs.m_pT?=?nullptr;
????}

????unique_ptr&?operator=(unique_ptr&&?rhs)
????{
????????this->m_pT?=?rhs.m_pT;
????????//源對象釋放
????????rhs.m_pT?=?nullptr;
????????return?*this;
????}

private:
????T*????m_pT;
};

這是?std::unique_ptr?具有移動語義的原因,希望讀者可以理解之。關于移動構造和?std::move,我們將在后面章節詳細介紹。

std::unique_ptr?不僅可以持有一個堆對象,也可以持有一組堆對象,示例如下:

#include?
#include?

int?main(){
????//創建10個int類型的堆對象
????//形式1
????std::unique_ptr<int[]>?sp1(new?int[10]);

????//形式2
????std::unique_ptr<int[]>?sp2;
????sp2.reset(new?int[10]);
????//形式3
????std::unique_ptr<int[]>?sp3(std::make_unique<int[]>(10));

????for?(int?i?=?0;?i?10;?++i)
????{
????????sp1[i]?=?i;
????????sp2[i]?=?i;
????????sp3[i]?=?i;
????}

????for?(int?i?=?0;?i?10;?++i)
????{
????????std::cout?<",?"?<",?"?<std::endl;
????}

????return?0;
}

程序執行結果如下:

[root@myaliyun?testmybook]#?g++?-g?-o?test_unique_ptr_with_array?test_unique_ptr_with_array.cpp?-std=c++17
[root@myaliyun?testmybook]#?./test_unique_ptr_with_array?
0,?0,?0
1,?1,?1
2,?2,?2
3,?3,?3
4,?4,?4
5,?5,?5
6,?6,?6
7,?7,?7
8,?8,?8
9,?9,?9

std::shared_ptr?和?std::weak_ptr?也可以持有一組堆對象,用法與?std::unique_ptr?相同,下文不再贅述。

自定義智能指針對象持有的資源的釋放函數

默認情況下,智能指針對象在析構時只會釋放其持有的堆內存(調用 delete 或者 delete[]),但是假設這塊堆內存代表的對象還對應一種需要回收的資源(如操作系統的套接字句柄、文件句柄等),我們可以通過自定義智能指針的資源釋放函數。假設現在有一個 Socket 類,對應著操作系統的套接字句柄,在回收時需要關閉該對象,我們可以如下自定義智能指針對象的資源析構函數,這里以?std::unique_ptr?為例:

#include?
#include?

class?Socket
{
public:
????Socket()
????{

????}

????~Socket()
????{

????}

????//關閉資源句柄
????void?close(){

????}
};

int?main(){
????auto?deletor?=?[](Socket*?pSocket)?{
????????//關閉句柄
????????pSocket->close();
????????//TODO:?你甚至可以在這里打印一行日志...
????????delete?pSocket;
????};

????std::unique_ptrvoid(*)(Socket?*?pSocket)>?spSocket(new?Socket(),?deletor);return?0;
}

自定義?std::unique_ptr?的資源釋放函數其規則是:

std::unique_ptr

其中 T 是你要釋放的對象類型,DeletorPtr 是一個自定義函數指針。上述代碼?33?行表示 DeletorPtr 有點復雜,我們可以使用?decltype(deletor)?讓編譯器自己推導 deletor 的類型,因此可以將?33?行代碼修改為:

std::unique_ptrdecltype(deletor)>?spSocket(new?Socket(),?deletor);

std::shared_ptr

std::unique_ptr?對其持有的資源具有獨占性,而?std::shared_ptr?持有的資源可以在多個?std::shared_ptr?之間共享,每多一個?std::shared_ptr?對資源的引用,資源引用計數將增加 1,每一個指向該資源的?std::shared_ptr?對象析構時,資源引用計數減 1,最后一個?std::shared_ptr?對象析構時,發現資源計數為 0,將釋放其持有的資源。多個線程之間,遞增和減少資源的引用計數是安全的。(注意:這不意味著多個線程同時操作?std::shared_ptr?引用的對象是安全的)。std::shared_ptr?提供了一個?use_count()?方法來獲取當前持有資源的引用計數。除了上面描述的,std::shared_ptr?用法和?std::unique_ptr?基本相同。

下面是一個初始化?std::shared_ptr?的示例:

//初始化方式1
std::shared_ptr<int>?sp1(new?int(123));

//初始化方式2
std::shared_ptr<int>?sp2;
sp2.reset(new?int(123));

//初始化方式3
std::shared_ptr<int>?sp3;
sp3?=?std::make_shared<int>(123);

和?std::unique_ptr?一樣,你應該優先使用?std::make_shared?去初始化一個?std::shared_ptr?對象。

再來看另外一段代碼:

#include?
#include?

class?A
{
public:
????A()
????{
????????std::cout?<"A?constructor"?<std::endl;
????}

????~A()
????{
????????std::cout?<"A?destructor"?<std::endl;
????}
};

int?main(){
????{
????????//初始化方式1
????????std::shared_ptr?sp1(new?A());std::cout?<"use?count:?"?<std::endl;//初始化方式2std::shared_ptr?sp2(sp1);std::cout?<"use?count:?"?<std::endl;
????????sp2.reset();std::cout?<"use?count:?"?<std::endl;
????????{std::shared_ptr?sp3?=?sp1;std::cout?<"use?count:?"?<std::endl;
????????}std::cout?<"use?count:?"?<std::endl;
????}return?0;
}
  • 上述代碼?22?行 sp1 構造時,同時觸發對象 A 的構造,因此 A 的構造函數會執行;

  • 此時只有一個 sp1 對象引用?22?行 new 出來的 A 對象(為了敘述方便,下文統一稱之為資源對象 A),因此代碼?24?行打印出來的引用計數值為?1

  • 代碼?27?行,利用 sp1 拷貝一份 sp2,導致代碼?28?行打印出來的引用計數為?2

  • 代碼?30?行調用 sp2 的 reset() 方法,sp2 釋放對資源對象 A 的引用,因此代碼?31?行打印的引用計數值再次變為?1

  • 代碼?34?行 利用 sp1 再次 創建 sp3,因此代碼?35?行打印的引用計數變為?2

  • 程序執行到?36?行以后,sp3 出了其作用域被析構,資源 A 的引用計數遞減 1,因此 代碼?38?行打印的引用計數為?1

  • 程序執行到?39?行以后,sp1 出了其作用域被析構,在其析構時遞減資源 A 的引用計數至?0,并析構資源 A 對象,因此類 A 的析構函數被調用。

所以整個程序的執行結果如下:

[root@myaliyun?testmybook]#?./test_shared_ptr_use_count?
A?constructoruse?count:?1
use?count:?2
use?count:?1
use?count:?2
use?count:?1
A?destructor

std::enable_shared_from_this

實際開發中,有時候需要在類中返回包裹當前對象(this)的一個?std::shared_ptr?對象給外部使用,C++ 新標準也為我們考慮到了這一點,有如此需求的類只要繼承自?std::enable_shared_from_this?模板對象即可。用法如下:

#include?
#include?

class?A?:?public?std::enable_shared_from_this
{public:
????A()
????{std::cout?<"A?constructor"?<std::endl;
????}
????~A()
????{std::cout?<"A?destructor"?<std::endl;
????}std::shared_ptr?getSelf()
????{return?shared_from_this();
????}
};int?main(){std::shared_ptr?sp1(new?A());std::shared_ptr?sp2?=?sp1->getSelf();std::cout?<"use?count:?"?<std::endl;return?0;
}

上述代碼中,類 A 的繼承?std::enable_shared_from_this?并提供一個?getSelf()?方法返回自身的?std::shared_ptr?對象,在?getSelf()?中調用?shared_from_this()?即可。

std::enable_shared_from_this?用起來比較方便,但是也存在很多不易察覺的陷阱。

陷阱一:不應該共享棧對象的 this 給智能指針對象

假設我們將上面代碼 main 函數?25?行生成 A 對象的方式改成一個棧變量,即:

//其他相同代碼省略...

int?main(){
????A?a;

????std::shared_ptr?sp2?=?a.getSelf();std::cout?<"use?count:?"?<std::endl;return?0;
}

運行修改后的代碼會發現程序在?std::shared_ptr sp2 = a.getSelf();?產生崩潰。這是因為,智能指針管理的是堆對象,棧對象會在函數調用結束后自行銷毀,因此不能通過?shared_from_this()?將該對象交由智能指針對象管理。切記:智能指針最初設計的目的就是為了管理堆對象的(即那些不會自動釋放的資源)

陷阱二:避免 std::enable_shared_from_this 的循環引用問題

再來看另外一段代碼:

//?test_std_enable_shared_from_this.cpp?:?This?file?contains?the?'main'?function.?Program?execution?begins?and?ends?there.
//
#include?
#include?

class?A?:?public?std::enable_shared_from_this
{public:
????A()
????{
????????m_i?=?9;//注意://比較好的做法是在構造函數里面調用shared_from_this()給m_SelfPtr賦值//但是很遺憾不能這么做,如果寫在構造函數里面程序會直接崩潰std::cout?<"A?constructor"?<std::endl;
????}
????~A()
????{
????????m_i?=?0;std::cout?<"A?destructor"?<std::endl;
????}void?func(){
????????m_SelfPtr?=?shared_from_this();
????}public:int?????????????????m_i;std::shared_ptr??m_SelfPtr;
};int?main(){
????{std::shared_ptr?spa(new?A());
????????spa->func();
????}return?0;
}

乍一看上面的代碼好像看不出什么問題,讓我們來實際運行一下看看輸出結果:

[root@myaliyun?testmybook]#?g++?-g?-o?test_std_enable_shared_from_this_problem?test_std_enable_shared_from_this_problem.cpp
[root@myaliyun?testmybook]#?./test_std_enable_shared_from_this_problem
A?constructor

我們發現在程序的整個生命周期內,只有 A 類構造函數的調用輸出,沒有 A 類析構函數的調用輸出,這意味著 new 出來的 A 對象產生了內存泄漏了!

我們來分析一下為什么 new 出來的 A 對象得不到釋放。當程序執行到?42?行后,spa 出了其作用域準備析構,在析構時其發現仍然有另外的一個 std::shared_ptr 對象即 A::m_SelfPtr 引用了 A,因此 spa 只會將 A 的引用計數遞減為 1,然后就銷毀自身了。現在留下一個矛盾的處境:必須銷毀 A 才能銷毀其成員變量 m_SelfPtr,而銷毀 m_SelfPtr 必須先銷毀 A。這就是所謂的 std::enable_shared_from_this 的循環引用問題。我們在實際開發中應該避免做出這樣的邏輯設計,這種情形下即使使用了智能指針也會造成內存泄漏。也就是說一個資源的生命周期可以交給一個智能指針對象,但是該智能指針的生命周期不可以再交給整個資源來管理。

std::weak_ptr

std::weak_ptr?是一個不控制資源生命周期的智能指針,是對對象的一種弱引用,只是提供了對其管理的資源的一個訪問手段,引入它的目的為協助?std::shared_ptr?工作。

std::weak_ptr?可以從一個?std::shared_ptr?或另一個?std::weak_ptr?對象構造,std::shared_ptr?可以直接賦值給?std::weak_ptr?,也可以通過?std::weak_ptr?的?lock()?函數來獲得?std::shared_ptr。它的構造和析構不會引起引用計數的增加或減少。std::weak_ptr?可用來解決?std::shared_ptr?相互引用時的死鎖問題(即兩個std::shared_ptr?相互引用,那么這兩個指針的引用計數永遠不可能下降為 0, 資源永遠不會釋放)。

示例代碼如下:

#include?
#include?

int?main(){
????//創建一個std::shared_ptr對象
????std::shared_ptr<int>?sp1(new?int(123));
????std::cout?<"use?count:?"?<std::endl;

????//通過構造函數得到一個std::weak_ptr對象
????std::weak_ptr<int>?sp2(sp1);
????std::cout?<"use?count:?"?<std::endl;

????//通過賦值運算符得到一個std::weak_ptr對象
????std::weak_ptr<int>?sp3?=?sp1;
????std::cout?<"use?count:?"?<std::endl;

????//通過一個std::weak_ptr對象得到另外一個std::weak_ptr對象
????std::weak_ptr<int>?sp4?=?sp2;
????std::cout?<"use?count:?"?<std::endl;

????return?0;
}

程序執行結果如下:

[root@myaliyun?testmybook]#?g++?-g?-o?test_weak_ptr?test_weak_ptr.cpp?
[root@myaliyun?testmybook]#?./test_weak_ptr
use?count:?1
use?count:?1
use?count:?1
use?count:?1

無論通過何種方式創建?std::weak_ptr?都不會增加資源的引用計數,因此每次輸出引用計數的值都是 1。

既然,std::weak_ptr?不管理對象的生命周期,那么其引用的對象可能在某個時刻被銷毀了,如何得知呢?std::weak_ptr?提供了一個?expired()?方法來做這一項檢測,返回 true,說明其引用的資源已經不存在了;返回 false,說明該資源仍然存在,這個時候可以使用?std::weak_ptr?的?lock()?方法得到一個?std::shared_ptr?對象然后繼續操作資源,以下代碼演示了該用法:

//tmpConn_?是一個?std::weak_ptr?對象
//tmpConn_引用的TcpConnection已經銷毀,直接返回
if?(tmpConn_.expired())
????return;

std::shared_ptr?conn?=?tmpConn_.lock();if?(conn)
{//對conn進行操作,省略...
}

有讀者可能對上述代碼產生疑問,既然使用了?std::weak_ptr?的?expired()?方法判斷了對象是否存在,為什么不直接使用?std::weak_ptr?對象對引用資源進行操作呢?實際上這是行不通的,std::weak_ptr?類沒有重寫?operator->?和?operator* 方法,因此不能像?std::shared_ptr?或?std::unique_ptr?一樣直接操作對象,同時?std::weak_ptr?類也沒有重寫?operator!?操作,因此也不能通過?std::weak_ptr?對象直接判斷其引用的資源是否存在:

#include?

class?A
{
public:
????void?doSomething(){

????}
};

int?main(){????
????std::shared_ptr?sp1(new?A());std::weak_ptr?sp2(sp1);//正確代碼if?(sp1)
????{//正確代碼
????????sp1->doSomething();
????????(*sp1).doSomething();
????}//正確代碼if?(!sp1)
????{
????}//錯誤代碼,無法編譯通過//if?(sp2)//{//????//錯誤代碼,無法編譯通過//????sp2->doSomething();//????(*sp2).doSomething();//}//錯誤代碼,無法編譯通過//if?(!sp2)//{//}return?0;
}

之所以?std::weak_ptr?不增加引用資源的引用計數不管理資源的生命周期,是因為,即使它實現了以上說的幾個方法,調用它們也是不安全的,因為在調用期間,引用的資源可能恰好被銷毀了,這會造成棘手的錯誤和麻煩。

因此,std::weak_ptr?的正確使用場景是那些資源如果可能就使用,如果不可使用則不用的場景,它不參與資源的生命周期管理。例如,網絡分層結構中,Session 對象(會話對象)利用 Connection 對象(連接對象)提供的服務工作,但是 Session 對象不管理 Connection 對象的生命周期,Session 管理 Connection 的生命周期是不合理的,因為網絡底層出錯會導致 Connection 對象被銷毀,此時 Session 對象如果強行持有 Connection 對象與事實矛盾。

std::weak_ptr?的應用場景,經典的例子是訂閱者模式或者觀察者模式中。這里以訂閱者為例來說明,消息發布器只有在某個訂閱者存在的情況下才會向其發布消息,而不能管理訂閱者的生命周期。

class?Subscriber
{

};

class?SubscribeManager
{
public:
????void?publish(){
????????for?(const?auto&?iter?:?m_subscribers)
????????{
????????????if?(!iter.expired())
????????????{
????????????????//TODO:給訂閱者發送消息
????????????}
????????}
????}

private:
????std::vector<std::weak_ptr>???m_subscribers;
};

智能指針對象的大小

一個?std::unique_ptr?對象大小與裸指針大小相同(即 sizeof(std::unique_ptr) == sizeof(void*)),而?std::shared_ptr?的大小是?std::unique_ptr?的一倍。以下是我分別在 Visual Studio 2019 和 gcc/g++ 4.8 上(二者都編譯成 x64 程序)的測試結果:

測試代碼

#include?
#include?
#include?

int?main(){
????std::shared_ptr<int>?sp0;
????std::shared_ptr<std::string>?sp1;
????sp1.reset(new?std::string());
????std::unique_ptr<int>?sp2;
????std::weak_ptr<int>?sp3;

????std::cout?<"sp0?size:?"?<sizeof(sp0)?<std::endl;
????std::cout?<"sp1?size:?"?<sizeof(sp1)?<std::endl;
????std::cout?<"sp2?size:?"?<sizeof(sp2)?<std::endl;
????std::cout?<"sp3?size:?"?<sizeof(sp3)?<std::endl;

????return?0;
}

Visual Studio 2019 運行結果:

gcc/g++ 運行結果:

在 32 位機器上,std_unique_ptr?占 4 字節,std::shared_ptr?和?std::weak_ptr?占 8 字節;在 64 位機器上,std_unique_ptr?占 8 字節,std::shared_ptr?和?std::weak_ptr?占 16 字節。也就是說,std_unique_ptr?的大小總是和原始指針大小一樣,std::shared_ptr?和?std::weak_ptr?大小是原始指針的一倍。

智能指針使用注意事項

C++ 新標準提倡的理念之一是不應該再手動調用 delete 或者 free 函數去釋放內存了,而應該把它們交給新標準提供的各種智能指針對象。C++ 新標準中的各種智能指針是如此的實用與強大,在現代 C++ 項目開發中,讀者應該盡量去使用它們。智能指針雖然好用,但稍不注意,也可能存在許多難以發現的 bug,這里我根據經驗總結了幾條:

  • 一旦一個對象使用智能指針管理后,就不該再使用原始裸指針去操作;

    看一段代碼:

    #include?

    class?Subscriber
    {

    };

    int?main(){????
    ??Subscriber*?pSubscriber?=?new?Subscriber();

    ??std::unique_ptr?spSubscriber(pSubscriber);delete?pSubscriber;return?0;
    }

    這段代碼利用創建了一個堆對象 Subscriber,然后利用智能指針 spSubscriber 去管理之,可以卻私下利用原始指針銷毀了該對象,這讓智能指針對象?spSubscriber?情何以堪啊?

    記住,一旦智能指針對象接管了你的資源,所有對資源的操作都應該通過智能指針對象進行,不建議再通過原始指針進行操作了。當然,除了?std::weak_ptrstd::unique_ptr?和?std::shared_ptr?都提供了獲取原始指針的方法——get()?函數。

    int?main(){????
    ??Subscriber*?pSubscriber?=?new?Subscriber();

    ??std::unique_ptr?spSubscriber(pSubscriber);//pTheSameSubscriber和pSubscriber指向同一個對象
    ??Subscriber*?pTheSameSubscriber=?spSubscriber.get();return?0;
    }
  • 分清楚場合應該使用哪種類型的智能指針;

    通常情況下,如果你的資源不需要在其他地方共享,那么應該優先使用?std::unique_ptr,反之使用?std::shared_ptr,當然這是在該智能指針需要管理資源的生命周期的情況下;如果不需要管理對象的生命周期,請使用?std::weak_ptr

  • 認真考慮,避免操作某個引用資源已經釋放的智能指針;

    前面的例子,一定讓你覺得非常容易知道一個智能指針的持有的資源是否還有效,但是還是建議在不同場景謹慎一點,有些場景是很容易造成誤判。例如下面的代碼:

    #include?
    #include?

    class?T
    {
    public:
    ??void?doSomething(){
    ??????std::cout?<"T?do?something..."?<std::endl;
    ??}

    private:
    ??int?????m_i;
    };

    int?main(){????
    ??std::shared_ptr?sp1(new?T());const?auto&?sp2?=?sp1;
    ??sp1.reset();//由于sp2已經不再持有對象的引用,程序會在這里出現意外的行為
    ??sp2->doSomething();return?0;
    }

    上述代碼中,sp2 是 sp1 的引用,sp1 被置空后,sp2 也一同為空。這時候調用 sp2->doSomething(),sp2->(即?operator->)在內部會調用?get()?方法獲取原始指針對象,這時會得到一個空指針(地址為 0),繼續調用 doSomething() 導致程序崩潰。

    你一定仍然覺得這個例子也能很明顯地看出問題,ok,讓我們把這個例子放到實際開發中再來看一下:

    //連接斷開
    void?MonitorServer::OnClose(const?std::shared_ptr&?conn)
    {????std::lock_guard<std::mutex>?guard(m_sessionMutex);for?(auto?iter?=?m_sessions.begin();?iter?!=?m_sessions.end();?++iter)
    ??{//通過比對connection對象找到對應的sessionif?((*iter)->GetConnectionPtr()?==?conn)
    ??????{
    ??????????m_sessions.erase(iter);//注意這里:程序在此處崩潰
    ??????????LOGI("monitor?client?disconnected:?%s",?conn->peerAddress().toIpPort().c_str());break;
    ??????}
    ??}
    }

    這段代碼不是我杜撰的,而是來自于我實際的一個商業項目中。注意代碼中我提醒注意的地方,該段程序會在代碼?12?行處崩潰,崩潰原因是調用了?conn->peerAddress()?方法。為什么這個方法的調用可能會引起崩潰?現在可以一目了然地看出了嗎?

    崩潰原因是傳入的 conn 對象和上一個例子中的 sp2 一樣都是另外一個?std::shared_ptr?的引用,當連接斷開時,對應的 TcpConnection 對象可能早已被銷毀,而 conn 引用就會變成空指針(嚴格來說是不再擁有一個 TcpConnection 對象),此時調用 TcpConnection 的 peerAddress() 方法就會產生和上一個示例一樣的錯誤。

  • 作為類成員變量時,應該優先使用前置聲明(forward declarations)

    我們知道,為了減小編譯依賴加快編譯速度和生成二進制文件的大小,C/C++ 項目中一般在 *.h 文件對于指針類型盡量使用前置聲明,而不是直接包含對應類的頭文件。例如:

    //Test.h
    //在這里使用A的前置聲明,而不是直接包含A.h文件
    class?A;

    class?Test
    {
    public:
    ??Test();
    ??~Test();

    private:
    ??A*??????m_pA;
    };

    同樣的道理,在頭文件中當使用智能指針對象作為類成員變量時,也應該優先使用前置聲明去引用智能指針對象的包裹類,而不是直接包含包裹類的頭文件。

    //Test.h
    #include?

    //智能指針包裹類A,這里優先使用A的前置聲明,而不是直接包含A.h
    class?A;

    class?Test
    {
    public:
    ??Test();
    ??~Test();

    private:??
    ??std::unique_ptr??m_spA;
    };

C++ 新標準中的智能指針我想介紹的就這么多了,Modern C/C++ 已經變為 C/C++ 開發的趨勢,希望讀者能善用和熟練使用本節介紹的后三種智能指針對象。

歷史推薦

1.?聊一聊程序員如何增加收入

2. 這一次我讓你徹底搞明白并發編程

3. 小方說服務器開發——一個實實在在幫你提高后端開發能力的地方

4. 一個 WebSocket 服務器是如何開發出來的?

5.?心跳包設計機制詳解

歡迎關注『高性能服務器開發』公眾號,一起交流服務器編程技藝與思想,也可以加入高性能服務器開發交流群:578019391?一起交流。

如果覺得對您有幫助,點擊“在看”支持下吧!

總結

以上是生活随笔為你收集整理的c++ 智能指针_详解 C++ 11 中的智能指针的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

激情影音先锋 | 免费视频xnxx com | 亚洲一区网站 | 人人干人人模 | www.国产高清 | 天天操操操操操操 | 欧美性黑人 | 亚洲免费成人av电影 | av高清在线观看 | 亚洲在线综合 | 亚洲女在线 | 最近中文字幕完整视频高清1 | 国产精品国产三级国产不产一地 | 国产成人一区二区三区久久精品 | 欧美一级激情 | 久久免费在线观看视频 | 看片网站黄 | www.狠狠插.com| 久草成人在线 | 人人射人人插 | 免费视频成人 | 国产午夜精品一区二区三区四区 | 韩国av电影网 | www蜜桃视频 | 一区二区在线影院 | 97在线观看视频国产 | 婷婷国产在线 | 激情自拍av | 久久午夜电影 | 中文字幕在线国产精品 | 国产黄a三级| 久久精品高清视频 | 99热最新网址| 蜜臀一区二区三区精品免费视频 | www.久久久.com| 国产精品青草综合久久久久99 | 91网站免费观看 | 射射色 | 午夜精品av在线 | 国产v在线 | 亚州中文av | 久久久久国产精品一区 | 激情综合五月婷婷 | 免费能看的av | 久久色视频 | 久久免费一 | 天躁狠狠躁 | 国产精品毛片一区二区 | 精品视频免费播放 | 中文字幕免费不卡视频 | 色婷婷福利视频 | 91亚洲国产成人 | 91av社区 | 中文字幕av日韩 | 91av精品 | 成人av网站在线播放 | 播五月综合 | 六月丁香久久 | 五月婷婷视频在线观看 | 天堂在线免费视频 | 成人国产电影在线观看 | 久久电影国产免费久久电影 | 国产小视频91 | av免费网页 | 麻豆久久一区二区 | 狠狠干狠狠久久 | 国产一区视频免费在线观看 | 在线观看精品一区 | 国产在线污 | 999在线视频 | 日本中文字幕高清 | av官网在线 | 在线观看日本高清mv视频 | www.av中文字幕.com | 久久国产精品系列 | 天堂网av 在线 | 97超碰伊人 | 日韩久久精品一区二区三区 | 99色婷婷 | 精品国产欧美 | 天天干天天操天天拍 | 国产视频二 | 99久久精品电影 | 国产精品国产毛片 | 国产精品久久久久久久久久三级 | 亚洲国产资源 | 久久婷婷精品 | 日韩高清免费无专码区 | 人人讲| 久久久久国产成人免费精品免费 | 国产精品一区二区美女视频免费看 | 日韩专区在线 | 亚洲成人二区 | 香蕉国产91 | 丁香影院在线 | 久久99视频免费 | 97超碰人人看 | 国产午夜精品久久久久久久久久 | 久久这里只有精品视频首页 | 欧美日韩免费在线观看视频 | 91视频 - 88av| 国产精品久久久av久久久 | 91高清完整版在线观看 | 午夜丁香视频在线观看 | 日韩精品欧美专区 | 欧美一区二区三区在线看 | 久久涩涩网站 | 综合铜03| 玖玖视频| 欧美在线视频日韩 | 性色大片在线观看 | 欧美色888 | 又湿又紧又大又爽a视频国产 | 干av在线| 国产91精品久久久久 | 久草在线91| 激情久久综合网 | 亚洲精品视频在线观看免费视频 | 免费看搞黄视频网站 | 超碰av在线播放 | 精品福利网 | 在线观看视频你懂 | 色综合久 | 久久国产高清视频 | 综合色婷婷 | 一区 在线 影院 | a级国产片| 久久久久久欧美二区电影网 | 精品在线观看国产 | 精品综合久久 | 最近中文国产在线视频 | 亚洲午夜久久久久久久久久久 | 激情中文在线 | 特黄免费av | 久久综合九色综合97_ 久久久 | 国产极品尤物在线 | 精品美女国产在线 | 中文字幕 国产 一区 | 韩国av永久免费 | 91在线观看视频网站 | 国产精品123 | 亚洲精品1区2区3区 超碰成人网 | 国产精品美女久久久久aⅴ 干干夜夜 | 99精品欧美一区二区蜜桃免费 | 九九九毛片 | 国产喷水在线 | 日韩在线高清视频 | 99re在线视频观看 | 狠狠躁夜夜躁人人爽视频 | 精品自拍sae8—视频 | 911国产在线观看 | 最新午夜电影 | 黄色av三级在线 | 久久99国产精品自在自在app | 国产视频一区在线 | 天天骚夜夜操 | 日韩久久一区二区 | 久久久久黄 | 日韩大片免费观看 | 亚洲少妇久久 | 99这里都是精品 | 色偷偷男人的天堂av | 午夜精品久久久久久久99 | 欧美精品久久久久久久久久白贞 | 欧美极品少妇xxxx | 久久国产品 | 中文字幕激情 | 日韩在线色视频 | 久久久久国产成人精品亚洲午夜 | 中日韩免费视频 | 久久视频精品在线 | 韩日精品视频 | 九九色综合 | 韩国三级av在线 | 又黄又爽的视频在线观看网站 | 性色av免费看 | 国产精品久久久一区二区三区网站 | 伊人官网| 国产91精品欧美 | 91在线影视 | 婷婷视频在线 | 毛片永久新网址首页 | 2022久久国产露脸精品国产 | 中文在线天堂资源 | 国产精品黄色av | 在线亚洲欧美视频 | 99久久久久久久久 | 亚洲精品播放 | www.人人草 | 激情视频综合网 | 久久久久久久久久久综合 | 免费手机黄色网址 | 色资源中文字幕 | 亚洲精品中文在线资源 | 毛片播放网站 | 999热线在线观看 | 人人爱人人做人人爽 | 日本精品久久久一区二区三区 | 97成人在线免费视频 | 视频在线观看入口黄最新永久免费国产 | 看黄色91 | 久久精国产 | 欧美污在线观看 | 久久天天躁夜夜躁狠狠85麻豆 | 91麻豆精品国产91久久久无需广告 | 在线免费观看羞羞视频 | 国产高清精品在线 | 看片网站黄 | 精品一区二区三区在线播放 | 九色视频自拍 | 91亚洲国产成人 | 999久久久久久久久久久 | 69国产盗摄一区二区三区五区 | 亚洲精品一区二区三区高潮 | 日韩精品一区二区三区电影 | 亚洲欧美乱综合图片区小说区 | 亚洲午夜久久久久久久久电影网 | 久久婷婷丁香 | 麻豆视频免费看 | 欧美在线视频二区 | 99国产成+人+综合+亚洲 欧美 | 色a网| avwww在线观看 | 免费看的国产视频网站 | 日本三级不卡视频 | 久久精品视频免费 | 成人在线免费观看视视频 | 毛片网站在线观看 | 日韩欧美在线高清 | 日本在线观看中文字幕无线观看 | 黄色三级网站在线观看 | 超碰在线日本 | 99在线播放 | 欧美a在线免费观看 | 日韩av午夜在线观看 | 色综合人人 | 日韩特级黄色片 | 成人小视频免费在线观看 | 综合色中色 | 久草视频手机在线 | 99热在线国产精品 | 蜜臀久久99精品久久久久久网站 | 色综合久久综合中文综合网 | 香蕉影院在线播放 | 99久久久国产精品免费99 | 亚洲成人频道 | 最新精品视频在线 | 久久美女高清视频 | 久草在线播放视频 | 色综合激情网 | 亚洲一区二区三区在线看 | 亚洲毛片视频 | 少妇性aaaaaaaaa视频 | 国产亚洲精品久久19p | 国产精品久久久久久久久久久久午夜 | 久久不射网站 | 91在线公开视频 | 18pao国产成视频永久免费 | 成年人国产在线观看 | 字幕网av| 久久99深爱久久99精品 | 天天操天天操天天操天天 | 69热国产视频 | 少妇bbbb搡bbbb搡bbbb | 亚洲理论在线观看 | 成片人卡1卡2卡3手机免费看 | 在线观看免费观看在线91 | 91亚瑟视频 | 日韩一区正在播放 | av免费在线观看1 | 久久久久电影网站 | 91免费视频网站在线观看 | 国产精品乱码久久久久 | 国产日韩中文字幕在线 | 色综合久久久久综合99 | 久久成人综合视频 | 免费午夜网站 | 精品在线一区二区 | 亚洲成a人片77777kkkk1在线观看 | 999精品视频| 国模吧一区| 亚洲综合在 | 五月婷婷另类国产 | 最新精品视频在线 | 久久久久久久99精品免费观看 | 免费久久网 | 精品影院一区二区久久久 | 亚洲精品白浆高清久久久久久 | 六月丁香在线视频 | 日本一区二区免费在线观看 | 日本激情视频中文字幕 | 亚洲欧美日韩国产一区二区三区 | 久青草电影 | 91亚洲精品国偷拍 | 免费观看视频的网站 | 99在线热播精品免费 | 免费久草视频 | 亚洲高清色综合 | 亚洲一区二区视频 | 又污又黄网站 | 精品久久久久久亚洲综合网 | 99视频久久 | 97夜夜澡人人爽人人免费 | 国产精彩视频一区二区 | 91最新在线| av在线最新 | 欧美色久 | 色丁香婷婷 | 国产精品99精品久久免费 | 亚洲精品网页 | 欧美精品一区二区性色 | 国产成人高清在线 | 日韩av电影国产 | 免费在线观看视频a | 国产理论影院 | 久久免费视频观看 | 天天干天天摸天天操 | 在线观看91 | 最近中文字幕完整视频高清1 | 91中文字幕视频 | 四虎国产精品成人免费4hu | 麻豆视频成人 | 午夜电影久久 | 亚洲国产精品成人va在线观看 | 男女激情片在线观看 | 麻豆mv在线观看 | 综合在线亚洲 | 黄色www | 欧美日韩国产页 | 国产精品久久亚洲 | 久久精品视频5 | 久久伊人国产精品 | 国产专区一 | 成年人免费在线观看网站 | 亚洲 欧美 成人 | 久久久国产一区二区 | 日韩午夜电影院 | 黄色片网站免费 | www.午夜色.com | 午夜久操 | 亚洲精品国偷自产在线99热 | 欧美久久久影院 | 中文字幕精品一区二区三区电影 | 99av国产精品欲麻豆 | 亚州精品在线视频 | 日韩大片免费观看 | 51久久成人国产精品麻豆 | 日日爽天天 | 黄色成人av网址 | 在线观看涩涩 | 日韩午夜电影网 | 99精品视频免费观看视频 | 成人午夜性影院 | 射久久久 | 99久久综合狠狠综合久久 | 超碰在线99 | 久久优| 成人免费视频播放 | 婷婷丁香色 | 六月丁香婷婷在线 | 欧美aaaxxxx做受视频 | 97在线观看免费观看高清 | 久久久久免费电影 | 91最新在线 | 在线免费性生活片 | 美女黄濒| 四虎亚洲精品 | av大全在线免费观看 | 亚洲成人精品在线观看 | 91精品国产麻豆国产自产影视 | 91av资源网 | 婷婷丁香视频 | 97超碰资源网| 四虎影院在线观看av | 久久综合导航 | 日韩电影在线一区 | 国产精品午夜8888 | 久久久久久免费 | 99综合久久 | 国产福利91精品一区二区三区 | 色综合天天综合 | 91精品久久久久久久99蜜桃 | 欧美日韩精品在线一区二区 | a天堂免费| 91中文字幕网 | 欧美精品在线视频观看 | 女女av在线 | 伊人色综合网 | 日本久久中文 | 成人毛片一区二区三区 | 色中文字幕在线观看 | 国产精品久久久久久久久软件 | 91亚洲激情 | 日韩精品一区二区三区第95 | 69av免费视频 | 日韩影视精品 | 免费污片| 久久综合加勒比 | 99视频精品 | 97色狠狠 | 天天舔天天搞 | 一区二区三区精品在线视频 | 国内精品视频一区二区三区八戒 | 蜜臀av夜夜澡人人爽人人 | av观看免费在线 | 奇米影视8888在线观看大全免费 | 久久综合久色欧美综合狠狠 | 国产精品免费观看久久 | 丁香五婷 | 久久色视频 | 日韩欧美一区二区三区免费观看 | 亚洲精品美女在线观看播放 | 人人狠狠综合久久亚洲婷 | 久久成熟| 香蕉在线视频观看 | 亚洲综合激情 | 久久成人视屏 | 欧美激情精品久久久久久免费印度 | 亚洲女在线 | 色免费在线 | 四虎影视成人精品 | 欧美精品网站 | 亚洲精品一区二区精华 | 丁香五月网久久综合 | 91精品成人| 国产精品久久久久免费 | 久久久www成人免费精品 | 色网站中文字幕 | 国产黑丝一区二区 | 日韩在线精品 | 黄色小网站在线观看 | 亚洲天天看 | www.久久成人 | 97操操| 国产男男gay做爰 | 免费精品国产 | 亚洲第五色综合网 | 美女视频黄免费 | www.97色.com| 久久久久久国产精品久久 | 日日综合 | 精品视频资源站 | 国产精品免费看久久久8精臀av | 亚洲国产成人久久综合 | 91免费版在线| www狠狠| 天堂在线成人 | 播五月综合 | 国产高清视频在线免费观看 | 欧美日韩一区二区在线观看 | 97福利在线观看 | 久久亚洲婷婷 | 天天操夜夜曰 | 日日日日干 | 亚洲精品久久久蜜臀下载官网 | 麻豆免费视频观看 | 激情丁香月 | 欧美日韩1区2区 | 久久久国产一区二区三区四区小说 | 欧美日韩国产精品爽爽 | 久久免费视频国产 | 亚洲免费在线 | 国产精品九九视频 | 丁香六月激情 | 中文字幕一区二区三区久久蜜桃 | 91av视频在线免费观看 | 福利久久 | 免费在线电影网址大全 | 友田真希x88av | 韩日色视频 | 天天拍天天草 | 欧美国产日韩在线观看 | 久爱精品在线 | 一区二区三区精品久久久 | 成人av网站在线播放 | 精品国内 | 91av福利视频 | 亚洲一区二区三区毛片 | 欧美激情片在线观看 | 欧美日一级片 | 国产二级视频 | 欧美一区二区精美视频 | 亚洲一区免费在线 | 中文字幕在线久一本久 | 中文字幕一区在线观看视频 | 国产精品免费一区二区三区 | 久久综合九色综合久久久精品综合 | 精品96久久久久久中文字幕无 | 99久久精品国产毛片 | 久久久久久久久久久福利 | 亚洲日韩中文字幕 | 丁香六月久久综合狠狠色 | 成人动漫精品一区二区 | 在线亚洲小视频 | 日本最新一区二区三区 | 日三级在线| 91污污视频在线观看 | 视频一区在线免费观看 | 中文字幕一区二区三区精华液 | 精品久久一区二区三区 | 天天射天天操天天 | 国产精品99久久免费黑人 | 一区二区三区免费 | 黄色成人av | 国产九色在线播放九色 | 国产精品v欧美精品 | 久久久国产精品一区二区三区 | 欧美在线视频一区二区三区 | 色欧美成人精品a∨在线观看 | 免费影视大全推荐 | 亚洲天堂精品视频 | 久久久久亚洲国产 | 91麻豆精品91久久久久同性 | 久久国产美女 | 99视频黄 | 国产精品久久久毛片 | 一区二区三区 中文字幕 | 精品国自产在线观看 | 日日操日日插 | 精品国内自产拍在线观看视频 | av中文在线| 久久99热精品这里久久精品 | 国产精品6| 99视频+国产日韩欧美 | 91精品国产91热久久久做人人 | 色a网| 婷婷丁香在线视频 | 2022久久国产露脸精品国产 | 免费看黄的 | 日韩手机在线观看 | 日本论理电影 | 国内综合精品午夜久久资源 | 成人黄色国产 | 国产精品久久久久久久久久免费看 | 亚洲区精品| 久香蕉| 国产精品高清免费在线观看 | 久久久久久久久影视 | 国内精品小视频 | 国内揄拍国产精品 | 91在线操 | www狠狠| 四虎永久网站 | 色综合久久久网 | 99久久国产免费,99久久国产免费大片 | 一区二区久久久久 | 91超碰免费在线 | 黄色三级在线 | 欧美淫视频 | 懂色av一区二区三区蜜臀 | 一区二区三区视频网站 | 一级特黄aaa大片在线观看 | 成年人免费在线 | 日韩精品国产一区 | 四虎永久免费网站 | 久久男人中文字幕资源站 | 亚洲视频久久久久 | 国产色就色 | 狠狠插狠狠操 | 亚洲日本精品视频 | 伊人www22综合色 | 色播激情五月 | 麻豆国产精品va在线观看不卡 | 黄色av电影网 | 91精品电影| 久久国产视频网 | 最新国产精品视频 | 97福利 | 日韩欧美视频在线免费观看 | 欧美性极品xxxx娇小 | 日韩视频免费看 | 9999在线观看 | 国产中文字幕一区 | 又爽又黄在线观看 | 中文字幕第| 97操操操 | 一本之道乱码区 | 91精品啪啪 | 日本在线视频一区二区三区 | 亚洲精品网址在线观看 | 五月的婷婷 | 成人免费毛片aaaaaa片 | 免费高清男女打扑克视频 | 99热在线国产精品 | 亚洲观看黄色网 | 五月婷婷六月综合 | 久久久久久国产精品免费 | 国产黄色电影 | 久久久久免费精品国产小说色大师 | 免费男女网站 | 久久人人精 | 成片免费观看视频大全 | 99热手机在线观看 | 亚洲一区二区三区毛片 | 91大神精品视频 | 国内一级片在线观看 | 国产成人精品综合久久久久99 | 五月婷婷综| 91九色pron| 在线岛国av | 一级免费av | 日韩在线一级 | 国内精品久久久久国产 | 日韩电影在线一区二区 | 午夜精品久久久久久久久久久久 | 成人黄大片 | 国产91全国探花系列在线播放 | 国产高清不卡 | 日日夜夜免费精品视频 | 日韩理论视频 | 日韩电影在线观看一区二区 | 国产人成一区二区三区影院 | 亚洲精品一区二区网址 | 日本婷婷色 | 久久综合国产伦精品免费 | 人交video另类hd | 超碰97国产精品人人cao | 亚洲aaa毛片 | 成年人在线免费看视频 | 日韩区欠美精品av视频 | 久久国产精品免费看 | 亚洲在线日韩 | 久久综合九色综合欧美就去吻 | 久草久| 亚洲人成人天堂h久久 | 国产黄色资源 | 精品影院| 射射射av | 天天操夜| 免费国产亚洲视频 | 狠狠干2018 | 97狠狠干| 天天看天天操 | 亚洲 欧美变态 另类 综合 | 天天草天天色 | 在线观看一 | 国产99久久久国产精品 | 国产精品www | .国产精品成人自产拍在线观看6 | 久草综合视频 | 久久在现视频 | 欧美另类视频 | avlulu久久精品 | 中文字幕av一区二区三区四区 | 国产精品av电影 | 国产精品一区二区免费看 | 99日精品 | 欧美日韩精品免费观看 | 国产精品一区二区久久久久 | 成年人三级网站 | 麻豆国产在线播放 | 欧美视频xxx | 狠狠久久 | 中文字幕欧美日韩va免费视频 | 亚洲毛片一区二区三区 | 成人精品999 | 综合久久精品 | 国产欧美最新羞羞视频在线观看 | 色综合久久久久综合体桃花网 | 成人免费网站在线观看 | 国产精品普通话 | 久久96国产精品久久99软件 | 日本三级久久久 | 国产精品成人自产拍在线观看 | 久久免费激情视频 | 国产成人一区二区三区影院在线 | 国产黄色精品在线 | 久久精品爱视频 | 欧美一区二区在线免费看 | 久久夜夜夜 | 一区二区三区四区精品视频 | 国产成在线观看免费视频 | 丰满少妇久久久 | 久草亚洲视频 | 樱空桃av | 丝袜制服天堂 | 日本不卡视频 | 日韩中文字幕国产 | 欧美一区成人 | 国产精品久久久久久a | 日韩欧美高清不卡 | 欧美在线视频一区二区 | 久久久久久免费毛片精品 | 婷五月天激情 | 久久久噜噜噜久久久 | 国产免费xvideos视频入口 | 国产精品一区二区av日韩在线 | 中文字幕你懂的 | 亚洲精品国产精品久久99热 | 亚洲一区二区三区四区精品 | 欧美精品一区二区在线观看 | 精品1区二区 | 国产高清专区 | 日韩高清一 | 999热视频| 日韩免费在线播放 | 精品一区二区在线免费观看 | 日韩欧美精品在线视频 | 99久久精品电影 | 成人在线观看你懂的 | 成人高清在线观看 | 久久免费视频网 | 亚洲高清资源 | 一区二区三区日韩视频在线观看 | 国产一级视频在线免费观看 | 狠狠色婷婷丁香六月 | 国产一级一级国产 | 一级片视频免费观看 | 免费v片 | 激情深爱.com | 中国美女一级看片 | 一区二区三区福利 | 国产一级一级国产 | www.亚洲黄色 | 久久免费公开视频 | 999成人精品| 亚洲综合激情小说 | 久操操 | 国产96av| 亚洲在线黄色 | 懂色av一区二区三区蜜臀 | 在线观看视频日韩 | 国产999免费视频 | 久久久国产网站 | 国产区欧美 | 狠狠的操你| 午夜免费福利视频 | 亚洲少妇xxxx | 成人91在线观看 | 久久免费看a级毛毛片 | 狠狠色噜噜狠狠 | 日韩在线精品 | 在线成人中文字幕 | 午夜在线日韩 | 六月丁香激情综合 | 国产一区精品在线 | 九九视频免费观看视频精品 | 91丨九色丨国产在线观看 | 亚a在线 | 婷婷四房综合激情五月 | 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 成av在线 | 久久久亚洲成人 | 国产在线播放一区二区三区 | 97在线精品 | 麻豆久久一区 | 欧美日韩亚洲在线观看 | 国产精品美女久久久久久久网站 | 欧美精品在线视频观看 | 久操久| 久草在线视频中文 | 成人久久18免费 | 99riav1国产精品视频 | 免费电影一区二区三区 | 91av超碰| 成人av动漫在线 | 亚洲做受高潮欧美裸体 | 99综合影院在线 | 免费日韩 | 99久久久国产精品美女 | 免费精品国产va自在自线 | www.色就是色 | 在线视频观看国产 | 国产成人av电影 | 在线天堂亚洲 | 免费成人结看片 | 日韩欧美一区二区在线播放 | 欧美黑人猛交 | 夜夜躁狠狠燥 | 99久久婷婷国产一区二区三区 | 久久免视频 | 777视频在线观看 | 久久国产麻豆 | 成人91在线观看 | 99精品视频网 | 亚洲精品免费看 | 99免费在线观看 | 久久精品视频在线观看免费 | 伊人久久精品久久亚洲一区 | 精品国产乱码一区二 | 黄网站www | 日韩欧美视频在线播放 | 一区二区伦理电影 | 国产亚洲午夜高清国产拍精品 | 69精品在线 | www久久99| av在线之家电影网站 | 天天操天天摸天天干 | 在线亚洲观看 | av先锋影音少妇 | 日韩视频1区 | 黄色福利视频网站 | 国产韩国日本高清视频 | 精品一区免费 | 日韩在线视 | 四虎小视频 | 久久精品com | 91丨porny丨九色 | 婷婷色视频 | 三级黄色免费片 | 91新人在线观看 | 国产亚洲精品久久久久秋 | 亚洲高清在线观看视频 | 亚洲成a人片综合在线 | 精品主播网红福利资源观看 | 免费av大全| 97精品国产手机 | 日韩精品中文字幕一区二区 | 久久久久电影 | 4hu视频 | 91精选在线 | h动漫中文字幕 | 激情在线免费视频 | 精品久久久久久久久久岛国gif | 国产视频九色蝌蚪 | 成人污视频在线观看 | 亚洲片在线观看 | 久久免费在线观看 | 99久久久久成人国产免费 | 日韩在线观看 | 欧美精品资源 | 五月婷婷操 | 九九九热精品免费视频观看网站 | 国产精品网红直播 | 欧美,日韩| 久久精品欧美一 | 亚洲国产日韩欧美在线 | 五月综合久久 | 中文字幕国语官网在线视频 | 黄色av一区二区三区 | 在线免费观看涩涩 | 亚洲男男gaygayxxxgv | 国产玖玖精品视频 | 久久综合五月 | 黄色精品一区二区 | 天天操福利视频 | 在线国产中文字幕 | 国产一区黄色 | 最新高清无码专区 | 欧美a级免费视频 | 中文字幕在线观看91 | 中文字幕一区二区三区久久蜜桃 | 免费在线观看av | 黄色毛片网站在线观看 | 久久九九影视 | 成人午夜电影在线播放 | 国产高清视频免费观看 | 在线免费视频 你懂得 | 91九色最新 | 日韩免费一级电影 | 丁香六月色 | 黄色免费网战 | 成人黄色在线电影 | www.久久爱.cn | 五月综合婷 | 中文字幕123区 | 亚洲无吗视频在线 | 中文字幕av在线电影 | 天天av资源| av大全在线免费观看 | 日日久视频 | 最近日本字幕mv免费观看在线 | 精品理论片 | 在线中文字幕视频 | 97视频免费在线观看 | 国产成人久久77777精品 | 激情网色 | 日韩精品免费一区二区在线观看 | 久久精品网站视频 | 久久高清毛片 | 日躁夜躁狠狠躁2001 | 午夜丁香网 | 九九影视理伦片 | 日本九九视频 | 久久天天躁狠狠躁亚洲综合公司 | 成人免费视频免费观看 | 欧美另类一二三四区 | 麻豆传媒视频在线免费观看 | 综合影视 | 欧美a级片免费看 | 午夜av色 | 天天看天天操 | 亚洲国产精品va在线看 | 日韩精品一区二区三区丰满 | 日本久久成人中文字幕电影 | 亚洲最大激情中文字幕 | 98超碰在线 | 狠狠干天天射 | 天天射天 | 国内精品视频免费 | 日韩av片免费在线观看 | 欧美性粗大hdvideo | 夜夜操天天干, | 久久在线 | 国产成人三级一区二区在线观看一 | 国产69精品久久99不卡的观看体验 | 黄色一区二区在线观看 | 男女全黄一级一级高潮免费看 | 天天透天天插 | aⅴ精品av导航 | 亚洲va男人天堂 | 久久久久综合视频 | 五月天久久精品 | 少妇精69xxtheporn | 欧美午夜激情网 | 色妞色视频一区二区三区四区 | 久久精品站 | 国产精品女人久久久久久 | 色99在线 | 久草观看 | 亚洲综合导航 | 天天色综合1 | 久在线 | 久久久国产99久久国产一 | 91少妇精拍在线播放 | 国产又粗又长又硬免费视频 | 天天爽夜夜爽人人爽一区二区 | 亚洲一二视频 | 好看的国产精品视频 | 国产美女免费 | 美女视频黄免费的 | 久久草草热国产精品直播 | 久热免费在线 | 69国产精品视频 | 欧美一二三区在线播放 | 黄色在线观看免费网站 | 91九色蝌蚪国产 | 99久热 | 日韩av偷拍 | 成人精品999 | 国产精品一区二区无线 | 天堂视频中文在线 | 永久精品视频 | 奇米网777 | 午夜精品一区二区三区在线观看 | 成人av在线直播 | 日韩视频在线不卡 | 天天综合网国产 | 日韩一二区在线 | 国产九色视频在线观看 | 麻豆va一区二区三区久久浪 | 91香蕉久久 | 亚洲伊人婷婷 | 色吊丝av中文字幕 | 日韩av电影国产 | 精品在线观看视频 | 高清精品视频 | 韩日成人av | 一区二区三区在线观看中文字幕 | 久久久久久久久久久影视 | 在线v | 成人动漫一区二区三区 | 黄色大全在线观看 | 国产精品爽爽久久久久久蜜臀 | 成人久久免费 | 精品在线观看视频 | 中文字幕高清av | 久久久久欠精品国产毛片国产毛生 | 一区二区三区在线观看 | 国产精品对白一区二区三区 | 亚洲国产资源 | 在线观看国产www | 91精品久久久久久综合乱菊 | 9ⅰ精品久久久久久久久中文字幕 | 成人福利在线观看 | 亚洲精品久久久蜜臀下载官网 | 最新av在线免费观看 | 在线看欧美 | 在线国产精品视频 | 免费看国产一级片 | 免费在线观看国产黄 | av专区在线 | 五月天天色 | 在线观看免费观看在线91 | 最新日韩在线 | 狠狠色丁香久久婷婷综合_中 | 亚洲资源视频 | 日韩精品一区二区免费 | 日本久久久久久 | 五月天久久久 | 久草在线视频资源 | 波多野结衣在线视频一区 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 久久久久久高潮国产精品视 | 精品一区三区 | 日韩av一区二区在线影视 | 国产露脸91国语对白 | 亚洲精品视频免费看 | 五月婷婷色丁香 | 久久久久综合网 | 欧美性超爽 | 日韩欧美中文 | 91激情视频在线观看 | 91av蜜桃 | 国产成在线观看免费视频 | 国产亚洲精品久 | 日本电影久久 | 精品国产一区二区三区在线观看 |