国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

現(xiàn)代C++之手寫智能指針

共 6456字,需瀏覽 13分鐘

 ·

2020-11-25 13:25

現(xiàn)代C++之手寫智能指針

0.回顧


所有代碼還是放在倉庫里面,歡迎star!

https://github.com/Light-City/CPlusPlusThings

前面一節(jié)編寫了一個RAII的例子:

class shape_wrapper {
public:
explicit shape_wrapper(
shape* ptr = nullptr)

: ptr_(ptr)
{}
~shape_wrapper()
{
delete ptr_;
}
shape* get() const { return ptr_; }
private:
shape* ptr_;
};

這個類可以完成智能指針的最基本的功能:對超出作用域的對象進行釋放。但它缺了點東 西:

  • 這個類只適用于 shape 類
  • 該類對象的行為不夠像指針
  • 拷貝該類對象會引發(fā)程序行為

1.手寫auto_ptr與scope_ptr

針對"這個類只適用于 shape 類",我們想到了模板,于是改造為:

template <typename  T>
class smater_ptr {
public:
explicit smater_ptr(
T* ptr = nullptr)

: ptr_(ptr)
{}
~smater_ptr()
{
delete ptr_;
}
T* get() const { return ptr_; }
private:
T* ptr_;
};

針對"該類對象的行為不夠像指針",我們想到了指針的基本操作有*,->,布爾表達式。

于是添加三個成員函數(shù):

template <typename  T>
class smater_ptr {
public:
...
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
operator bool() const { return ptr_; }
...
private:
T* ptr_;
};

針對"拷貝該類對象會引發(fā)程序行為",我們想到了拷貝構(gòu)造和賦值。

現(xiàn)考慮如下調(diào)用:

smart_ptr ptr1{create_shape(shape_type::circle)};
smart_ptr ptr2{ptr1};

對于第二行,究竟應(yīng)當讓編譯時發(fā)生錯誤,還是可以有一個更合理的行為?我們來逐一檢查 一下各種可能性。最簡單的情況顯然是禁止拷貝。我們可以使用下面的代碼:

template <typename T>
class smart_ptr {

smart_ptr(const smart_ptr&)
= delete;
smart_ptr& operator=(const smart_ptr&)
= delete;

};

當然,也可以設(shè)為private。

禁用這兩個函數(shù)非常簡單,但卻解決了一種可能出錯的情況。否則,smart_ptr ptr2{ptr1}; 在編譯時不會出錯,但在運行時卻會有未定義行為——由于會對同一內(nèi)存釋放兩次,通常情況下會導致程序崩潰。

我們是不是可以考慮在拷貝智能指針時把對象拷貝一份?不行,通常人們不會這么用,因為使用智能指針的目的就是要減少對象的拷貝啊。何況,雖然我們的指針類型是 shape,但實際指向的卻應(yīng)該是 circle 或 triangle 之類的對象。在 C++ 里沒有像 Java 的clone 方法這樣的約定;一般而言,并沒有通用的方法可以通過基類的指針來構(gòu)造出一個子類的對象來。

那關(guān)鍵點就來了,所有權(quán)!,我們可以拷貝時轉(zhuǎn)移指針的所有權(quán)!下面實現(xiàn)便是auto_ptr的核心實現(xiàn):

template<typename T>
class auto_ptr {
public:
explicit auto_ptr(
T *ptr = nullptr)
noexcept
: ptr_(ptr)
{}

~auto_ptr() noexcept {
delete ptr_;
}
// 返回值為T&,允許*ptr=10操作
T &operator*() const noexcept { return *ptr_; }

T *operator->() const noexcept { return ptr_; }

operator bool() const noexcept { return ptr_; }

T *get() const noexcept { return ptr_; }

// 拷貝構(gòu)造,被復制放釋放原來指針的所有權(quán),交給復制方
auto_ptr(auto_ptr &other) noexcept {
ptr_ = other.release();
}

// copy and swap
auto_ptr &operator=(auto_ptr &rhs) noexcept {
// auto_ptr tmp(rhs.release());
// tmp.swap(*this);
// s上述兩行等價于下面一行
auto_ptr(rhs.release()).swap(*this);
return *this;
}

// 原來的指針釋放所有權(quán)
T *release() noexcept {
T *ptr = ptr_;
ptr_ = nullptr;
return ptr;
}

void swap(auto_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_); // 轉(zhuǎn)移指針所有權(quán)
}

private:
T *ptr_;
};

template<typename T>
void swap(auto_ptr &lhs, auto_ptr &rhs) noexcept {
lhs.swap(rhs);
}

int main() {
auto_ptr ptr1{create_shape(shape_type::circle)};
auto_ptr ptr2{ptr1};
if (ptr1.get() == nullptr && ptr2.get())
cout << "拷貝構(gòu)造:ptr1釋放了所有權(quán),ptr2獲得了所有權(quán)" << endl;
ptr1 = ptr1;

auto_ptr ptr3{create_shape(shape_type::rectangle)};
ptr1 = ptr3;

if (ptr3.get() == nullptr && ptr1.get())
cout << "賦值操作:始終只有一個對象管理一個區(qū)塊!ptr3釋放了所有權(quán),ptr1獲得了所有權(quán)" << endl;
}

上述通過copy-swap技術(shù)完成了避免自我賦值與保證了強異常安全!

如果你覺得這個實現(xiàn)還不錯的話,那恭喜你,你達到了 C++ 委員會在 1998 年時的水平:上面給出的語義本質(zhì)上就是 C++98 的 auto_ptr 的定義。如果你覺得這個實現(xiàn)很別扭的話,也恭喜你,因為 C++ 委員會也是這么覺得的:auto_ptr 在 C++17 時已經(jīng)被正式從C++ 標準里刪除了。

上面會導致什么問題呢?

看一下輸出結(jié)果:

shape
circle
拷貝構(gòu)造:ptr1釋放了所有權(quán),ptr2獲得了所有權(quán)
shape
rectangle
賦值操作:始終只有一個對象管理一個區(qū)塊!ptr3釋放了所有權(quán),ptr1獲得了所有權(quán)

shape與circle實在create_shape時候輸出的,我們重點關(guān)注最后一句話,發(fā)現(xiàn)了一個很大的問題:它的行為會讓程序員非常容易犯錯。一不小心把它傳遞給另外一個 auto_ptr,你就不再擁有這個對象了。

上述拷貝構(gòu)造與拷貝賦值分別如下面兩張圖所示:

圖1

圖2

針對這個問題,在C++11標準出來之前,C++98標準中都一直只有一個智能指針auto_ptr,我們知道,這是一個失敗的設(shè)計。它的本質(zhì)是管理權(quán)的轉(zhuǎn)移,這有許多問題。而這時就有一群人開始擴展C++標準庫的關(guān)于智能指針的部分,他們組成了boost社區(qū),他們負責boost庫的開發(fā)和維護。其目的是為C++程序員提供免費的、同行審查的、可移植的程序庫。boost庫可以和C++標準庫完美的共同工作,并且為其提供擴展功能?,F(xiàn)在的C++11標準庫的智能指針很大程度上“借鑒”了boost庫。

boost::scoped_ptr 屬于 boost 庫,定義在 namespace boost 中,包含頭文件#include可以使用。scoped_ptr 跟 auto_ptr 一樣,可以方便的管理單個堆內(nèi)存對象,特別的是,scoped_ptr 獨享所有權(quán),避免了auto_ptr惱人的幾個問題。

scoped_ptr是一種簡單粗暴的設(shè)計,它本質(zhì)就是防拷貝,避免出現(xiàn)管理權(quán)的轉(zhuǎn)移。這是它的最大特點,所以他的拷貝構(gòu)造函數(shù)和賦值運算符重載函數(shù)都只是聲明而不定義,而且為了防止有的人在類外定義,所以將函數(shù)聲明為private。但這也是它最大的問題所在,就是不能賦值拷貝,也就是說功能不全。但是這種設(shè)計比較高效、簡潔。沒有 release() 函數(shù),不會導致先前的內(nèi)存泄露問題。下面我也將模擬實現(xiàn)scoped_ptr的管理機制(實際上就是前面提到的禁止拷貝):

template<class T>
class scoped_ptr // noncopyable
{


public:
explicit scoped_ptr(T *ptr = 0) noexcept : ptr_(ptr) {
}

~scoped_ptr() noexcept {
delete ptr_;
}

void reset(T *p = 0) noexcept {
scoped_ptr(p).swap(*this);
}

T &operator*() const noexcept {
return *ptr_;
}

T *operator->() const noexcept {
return ptr_;
}

T *get() const noexcept {
return ptr_;
}

void swap(scoped_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_);
}

private:
T *ptr_;

scoped_ptr(scoped_ptr const &);
scoped_ptr &operator=(scoped_ptr const &);
};

template<typename T>
void swap(scoped_ptr &lhs, scoped_ptr &rhs) noexcept {
lhs.swap(rhs);
}

scoped_ptr特點總結(jié):

1)與auto_ptr類似,采用棧上的指針去管理堆上的內(nèi)容,從而使得堆上的對象隨著棧上對象銷毀時自動刪除;

2)scoped_ptr有著更嚴格的使用限制——不能拷貝,這也意味著scoped_ptr不能轉(zhuǎn)換其所有權(quán),所以它管理的對象不能作為函數(shù)的返回值,對象生命周期僅僅局限于一定區(qū)間(該指針所在的{}區(qū)間,而std::auto_ptr可以);

3)由于防拷貝的特性,使其管理的對象不能共享所有權(quán),這與std::auto_ptr類似,這一特點使該指針簡單易用,但也造成了功能的薄弱。

2.手寫unique_ptr之子類向基類轉(zhuǎn)換

在上述auto_ptr基礎(chǔ)上,我們把拷貝構(gòu)造與拷貝賦值,改為移動構(gòu)造與移動賦值。

template<typename T>
class unique_ptr {
public:
explicit unique_ptr(
T *ptr = nullptr)
noexcept
: ptr_(ptr)
{}

~unique_ptr() noexcept {
delete ptr_;
}

T &operator*() const noexcept { return *ptr_; }

T *operator->() const noexcept { return ptr_; }

operator bool() const noexcept { return ptr_; }

T *get() const noexcept { return ptr_; }

unique_ptr(unique_ptr &&other) noexcept {
ptr_ = other.release();
}

// copy and swap 始終只有一個對象有管理這塊空間的權(quán)限
unique_ptr &operator=(unique_ptr rhs) noexcept {
rhs.swap(*this);
return *this;
}

// 原來的指針釋放所有權(quán)
T *release() noexcept {
T *ptr = ptr_;
ptr_ = nullptr;
return ptr;
}

void swap(unique_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_); // 轉(zhuǎn)移指針所有權(quán)
}

private:
T *ptr_;
};
template<typename T>
void swap(unique_ptr &lhs, unique_ptr &rhs) {
lhs.swap(rhs);
}

調(diào)用:

int main() {
unique_ptr ptr1{create_shape(shape_type::circle)};
// unique_ptr ptr2{ptr1}; // error
unique_ptr ptr2{std::move(ptr1)}; // ok

unique_ptr ptr3{create_shape(shape_type::rectangle)};
// ptr1 = ptr3; // error
ptr3 = std::move(ptr1); // ok
}

把拷貝構(gòu)造函數(shù)中的參數(shù)類型 unique_ptr& 改成了 unique_ptr&&;現(xiàn)在它成了移動構(gòu)造函數(shù)。把賦值函數(shù)中的參數(shù)類型 unique_ptr& 改成了 unique_ptr,在構(gòu)造參數(shù)時直接生成新的智能指針,從而不再需要在函數(shù)體中構(gòu)造臨時對象?,F(xiàn)在賦值函數(shù)的行為是移動還是拷貝,完全依賴于構(gòu)造參數(shù)時走的是移動構(gòu)造還是拷貝構(gòu)造。

最后,一個circle* 是可以隱式轉(zhuǎn)換成 shape*的,但上面的 unique_ptr 卻無法自動轉(zhuǎn)換成 unique_ptr。

現(xiàn)在我們考慮兩種情況:

(1)第一種:當我們只是在原先的移動構(gòu)造上面添加template ,此時情況是移動構(gòu)造變?yōu)閹0宓囊苿訕?gòu)造,可以進行子類向基類轉(zhuǎn)換,但是與移動構(gòu)造相關(guān)的,則調(diào)用的是默認移動構(gòu)造,除非是子類向基類轉(zhuǎn)換,才調(diào)用帶模板的移動構(gòu)造。

template <typename U>
unique_ptr(unique_ptr &&other) noexcept {
ptr_ = other.release();
}

六個特殊的成員函數(shù)其生成規(guī)則如下:

  • 默認構(gòu)造函數(shù),生成規(guī)則和C++98一樣,在用戶沒有聲明自定義的構(gòu)造函數(shù)的時候并且編譯期需要的時候生成。
  • 析構(gòu)函數(shù),生成規(guī)則和C++98一樣,在C++11中有點不同的是,析構(gòu)函數(shù)默認是noexcept。
  • 拷貝構(gòu)造函數(shù),用戶自定義了移動操作會導致不生成默認的拷貝構(gòu)造函數(shù),其它和C++98的行為一致。
  • 拷貝賦值操作符,用戶自定義了移動操作會導致不生成默認的拷貝賦值操作,其它和C++98的行為一致。
  • 移動構(gòu)造函數(shù)和移動賦值操作符,僅僅在沒有用戶自定義的拷貝操作,移動操作和析構(gòu)操作的時候才會生成。

根據(jù)《Effective Modern C++》Item17 P115頁提到,當類中含有特殊成員函數(shù)變?yōu)槟0逄厥獬蓡T函數(shù)的時候,此時不滿足上述生成規(guī)則,也就是針對當前例子來說,編譯器會默認生成拷貝構(gòu)造,所以此時上述main調(diào)用里面為error的都可以正常運行!

int main() {
unique_ptr ptr1{create_shape(shape_type::circle)};
unique_ptr ptr2{ptr1}; // 由于帶模板的移動構(gòu)造函數(shù)引發(fā)編譯器會默認生成拷貝構(gòu)造
if (ptr1.get() != nullptr) // bitwise copy 此時ptr1不為NULL
ptr2.get()->print();

unique_ptr ptr2_2{std::move(ptr1)}; // 調(diào)用的是默認的移動構(gòu)造,而不是帶模板的移動構(gòu)造 bitwise move
if (ptr2_2.get() != nullptr && ptr1.get() != nullptr) // ptr1 不為空
ptr2_2.get()->print();

unique_ptr ptr3{create_shape(shape_type::rectangle)};
ptr1 = ptr3; // ok 根據(jù)形參先調(diào)用默認拷貝,再調(diào)用拷貝賦值
ptr3 = std::move(ptr1); // ok 根據(jù)形參先調(diào)用默認移動構(gòu)造,而不是帶參數(shù)的移動構(gòu)造,再調(diào)用移動賦值
unique_ptr ptr4(std::move(new circle)); // ok 調(diào)用帶模板的移動構(gòu)造
}

調(diào)用與結(jié)果如上代碼所示。

(2)第二種:移動構(gòu)造與帶模板的移動構(gòu)造同時存在,可以完成子類向基類的轉(zhuǎn)換,此時是滿足上述生成規(guī)則,此時不會生成拷貝函數(shù)!

int main() {
unique_ptr ptr1{create_shape(shape_type::circle)};
// unique_ptr ptr2{ptr1}; // error
unique_ptr ptr2_2{std::move(ptr1)}; // ok
if (ptr2_2.get() != nullptr && ptr1.get() == nullptr)
ptr2_2.get()->print();

unique_ptr ptr3{create_shape(shape_type::rectangle)};
// ptr1 = ptr3; // error
ptr3 = std::move(ptr1); // ok
// unique_ptr cl{create_shape(shape_type::circle)}; // error 因為create_shape返回的是shape 不能基類轉(zhuǎn)子類
unique_ptr cl{new circle()};
unique_ptr ptr5(std::move(cl)); // ok unique轉(zhuǎn)unique
}

小結(jié):

(1)我們需要了解子類向基類的隱式轉(zhuǎn)換,通過將移動構(gòu)造函數(shù)變?yōu)閹0宓囊苿訕?gòu)造函數(shù),要明白兩者共存情況與只有帶模板的移動或者其他構(gòu)造函數(shù)對編譯器生成規(guī)則的影響!上述代碼,此時還不能完成基類向子類的轉(zhuǎn)換!例如:unique_ptr轉(zhuǎn)unique_ptr。

(2)auto_ptr與unique_tr都是獨占所有權(quán),每次只能被單個對象所擁有,unique_ptr與auto_ptr不同的是使用移動語義來顯示的編寫。auto_ptr是可以說你隨便賦值,但賦值完了之后原來的對象就不知不覺的報廢.搞得你莫名其妙。而unique_ptr就干脆不讓你可以隨便去復制,賦值.如果實在想傳個值就哪里,顯式的說明內(nèi)存轉(zhuǎn)移std:move一下。然后這樣傳值完了之后,之前的對象也同樣報廢了.只不過整個move你讓明顯的知道這樣操作后會導致之前的unique_ptr對象失效。scope_ptr則是直接不允許拷貝。由于防拷貝的特性,使其管理的對象不能共享所有權(quán)。

3.shared_ptr之引用計數(shù)

unique_ptr 算是一種較為安全的智能指針了。但是,一個對象只能被單個 unique_ptr所擁有,這顯然不能滿足所有使用場合的需求。一種常見的情況是,多個智能指針同時擁有一個對象;當它們?nèi)慷际r,這個對象也同時會被刪除。這也就是 shared_ptr 了。

兩者區(qū)別如下:

多個shared_ptr不僅共享一個對象,同時還得共享同一個計數(shù)。當最后一個指向?qū)ο?和共享計數(shù))的shared_ptr析構(gòu)時,它需要刪除對象和共享計數(shù)。

首先需要一個共享計數(shù)的實現(xiàn):

class shared_count {
public:
shared_count() : count_(1) {

}

// 增加計數(shù)
void add_count() {
++count_;
}

// 減少計數(shù)
long reduce_count() {
return --count_;
}

// 獲取當前計數(shù)
long get_count() const {
return count_;
}

private:
long count_;
};

接下來實現(xiàn)引用計數(shù)智能指針:

構(gòu)造與析構(gòu)、swap實現(xiàn)如下所示:

template<typename T>
class shared_ptr {
public:
explicit shared_ptr(
T *ptr = nullptr)
noexcept
: ptr_(ptr)
{
if (ptr) {
shared_count_ = new shared_count();
}
}

~shared_ptr() noexcept {
// 最后一個shared_ptr再去刪除對象與共享計數(shù)
// ptr_不為空且此時共享計數(shù)減為0的時候,再去刪除
if(ptr_&&!shared_count_->reduce_count()) {
delete ptr_;
delete shared_count_;
}
}

void swap(shared_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_);
swap(shared_count_,rhs.shared_count_);
}

private:
T *ptr_;
shared_count *shared_count_;
};
template<typename T>
void swap(shared_ptr &lhs, shared_ptr &rhs) noexcept {
lhs.swap(rhs);
}

之前的賦值函數(shù),編譯器可以根據(jù)調(diào)用來決定是調(diào)拷貝構(gòu)造還是移動構(gòu)函數(shù),所以不變:

// copy and swap  始終只有一個對象有管理這塊空間的權(quán)限
shared_ptr &operator=(shared_ptr rhs) noexcept {
rhs.swap(*this);
return *this;
}

拷貝構(gòu)造與移動構(gòu)造需要改變:

除復制指針之外,對于拷貝構(gòu)造的情況,我們需要在指針非空時把引用數(shù)加一,并復制共享 計數(shù)的指針。對于移動構(gòu)造的情況,我們不需要調(diào)整引用數(shù),直接把 other.ptr_ 置為 空,認為 other 不再指向該共享對象即可

實現(xiàn)如下所示:

template<typename U>
shared_ptr(const shared_ptr &other) noexcept {
ptr_ = other.ptr_;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}

template<typename U>
shared_ptr(shared_ptr &&other) noexcept {
ptr_ = other.ptr_;
if (ptr_) {
shared_count_ = other.shared_count_;
other.shared_count_ = nullptr;
}
}

當運行的時候,報錯:

‘circle* shared_ptr::ptr_’ is private

錯誤原因是模板的各個實例間并不天然就有 friend 關(guān)系,因而不能互訪私有成員 ptr_shared_count_。我們需要在 smart_ptr 的定義中顯式聲明:

template<typename U>
friend class shared_ptr;

此外,在當前引用計數(shù)實現(xiàn)中,我們應(yīng)該刪除release釋放所有權(quán)函數(shù),編寫一個返回引用計數(shù)值的函數(shù)。

long use_count() const noexcept {
if (ptr_) {
return shared_count_->get_count();
} else {
return 0;
}
}

調(diào)用:

shared_ptr ptr1(new circle());
cout << "use count of ptr1 is " << ptr1.use_count() << endl;
shared_ptr ptr2, ptr3;
cout << "use count of ptr2 was " << ptr2.use_count() << endl;
ptr2 = ptr1; // shared_ptr隱式轉(zhuǎn)換shared_ptr 調(diào)用帶模板的拷貝構(gòu)造
// cout<<"======="<
// ptr3 = ptr2; // 調(diào)用的是編譯器生成的默認拷貝構(gòu)造 所以引用計數(shù)不會增加 ptr3=ptr2
// cout<<"======="<
ptr3 = ptr1;
cout << "此時3個shared_ptr指向同一個資源" << endl;
cout << "use count of ptr1 is now " << ptr1.use_count() << endl;
cout << "use count of ptr2 is now " << ptr2.use_count() << endl;
cout << "use count of ptr3 is now " << ptr3.use_count() << endl;
if (ptr1)
cout << "ptr1 is not empty" << endl;
// 會先調(diào)用賦值函數(shù),由編譯器決定調(diào)用的是拷貝構(gòu)造還是移動構(gòu)造,造出一個新的臨時對象出來,臨時對象會在跳出作用域后被析構(gòu)掉。
// 在析構(gòu)函數(shù)中,會先判斷該臨時對象的是否指向資源,如果沒有,析構(gòu)結(jié)束。否則,對引用計數(shù)減1,判斷引用計數(shù)是否為0,如果為0,刪除共享引用計數(shù)指針,否則不操作。
cout << "此時2個shared_ptr指向同一個資源" << endl;
ptr2 = std::move(ptr1);
if (!ptr1 && ptr2) { // 調(diào)用的是bool重載操作符
cout << "ptr1 move to ptr2" << endl;
cout << "use count of ptr1 is now " << ptr1.use_count() << endl;
cout << "use count of ptr2 is now " << ptr2.use_count() << endl;
cout << "use count of ptr3 is now " << ptr3.use_count() << endl;
}

輸出:

shape
circle
use count of ptr1 is 1
use count of ptr2 was 0
此時3shared_ptr指向同一個資源
use count of ptr1 is now 3
use count of ptr2 is now 3
use count of ptr3 is now 3
ptr1 is not empty
此時2shared_ptr指向同一個資源
ptr1 move to ptr2
use count of ptr1 is now 0
use count of ptr2 is now 2
use count of ptr3 is now 2
~circle
~shape

有幾點注意事項:

  • 上述代碼沒有考慮線程安全性,這里只是簡化版

  • =賦值重載函數(shù)不加&,編譯器決定調(diào)用拷貝構(gòu)造還是移動構(gòu)造,來造出一個臨時對象出來。

  • 根據(jù)前面提到的,當類中特殊函數(shù)變?yōu)閹0宓暮瘮?shù),編譯器仍然會生成默認拷貝構(gòu)造與默認移動構(gòu)造。

針對第一點:例如:ptr2 = std::move(ptr1);

會先調(diào)用賦值函數(shù),由編譯器決定調(diào)用的是拷貝構(gòu)造還是移動構(gòu)造,造出一個新的臨時對象出來,臨時對象會在跳出作用域后被析構(gòu)掉。在析構(gòu)函數(shù)中,會先判斷該臨時對象的是否指向資源,如果沒有,析構(gòu)結(jié)束。否則,對引用計數(shù)減1,判斷引用計數(shù)是否為0,如果為0,刪除共享引用計數(shù)指針,否則不操作。

針對第二點:

shared_ptr ptr2, ptr3;
ptr3 = ptr2; // 調(diào)用的是編譯器生成的默認拷貝構(gòu)造 所以引用計數(shù)不會增加

兩者都是一種類型,所以在調(diào)用賦值操作后,不會調(diào)用帶模板的拷貝構(gòu)造來創(chuàng)建臨時變量,而是調(diào)用編譯器生成的默認拷貝構(gòu)造,所以此時引用計數(shù)不會增加。

4.指針類型轉(zhuǎn)換

對應(yīng)于 C++ 里的不同的類型強制轉(zhuǎn):

  • dynamic_cast
  • static_cast
  • const_cast
  • reinterpret_cast

4.1 dynamic_cast

在上述unique_ptr處實現(xiàn)了子類向基類的轉(zhuǎn)換,但是卻沒有實現(xiàn)基類向子類的轉(zhuǎn)換,例如::unique_ptr轉(zhuǎn)unique_ptr。

實現(xiàn)這種,需要使用dynamic_cast,實現(xiàn)如下:

首先為了實現(xiàn)這些轉(zhuǎn)換,我們需要添加構(gòu)造函數(shù),允許在對智能指針內(nèi)部的指針對象賦值時,使用一個現(xiàn)有的智能指針的共享計數(shù)。

// 實現(xiàn)強制類型轉(zhuǎn)換需要的構(gòu)造函數(shù)
template<typename U>
shared_ptr(const shared_ptr &other, T *ptr) noexcept {
ptr_ = ptr;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}

其次,就是實現(xiàn)轉(zhuǎn)換函數(shù):

template<typename T, typename U>
shared_ptr dynamic_pointer_cast(const shared_ptr &other) noexcept {
T *ptr = dynamic_cast(other.get());
return shared_ptr(other, ptr);
}

調(diào)用:

// shape* -> circle* 使用dynamic_cast轉(zhuǎn)換后,指針為空.此時資源還是被dptr2擁有,dptr1為0
shared_ptr dptr2(new shape);
shared_ptr dptr1 = dynamic_pointer_cast(dptr2); // 基類轉(zhuǎn)子類

cout << "use count of dptr1 is now " << dptr1.use_count() << endl; // 0
cout << "use count of dptr2 is now " << dptr2.use_count() << endl; // 1

// circle* -> circle* 使用dynamic_cast轉(zhuǎn)換后,指針不為空,此時資源被兩者共同使用,引用計數(shù)為2
shared_ptr dptr3(new circle);
// shared_ptr dptr3(new circle); // 上面或者當前行,后面輸出一樣!
shared_ptr dptr1_1 = dynamic_pointer_cast(dptr3); // 基類轉(zhuǎn)子類

cout << "use count of dptr1_1 is now " << dptr1_1.use_count() << endl; // 2
cout << "use count of dptr3 is now " << dptr3.use_count() << endl; // 2

// circle* -> circle* 使用dynamic_cast轉(zhuǎn)換后,指針不為空,此時資源被兩者共同使用,引用計數(shù)為2
shared_ptr dptr3_1(new circle);
shared_ptr dptr2_1 = dynamic_pointer_cast(dptr3_1); // 子類轉(zhuǎn)基類 上行轉(zhuǎn)換,安全!

cout << "use count of dptr2_1 is now " << dptr2_1.use_count() << endl; // 2
cout << "use count of dptr3_1 is now " << dptr3_1.use_count() << endl; // 2

dynamic_cast主要用于類層次間的上行轉(zhuǎn)換和下行轉(zhuǎn)換,還可以用于類之間的交叉轉(zhuǎn)換。在類層次間進行上行轉(zhuǎn)換時,dynamic_cast和static_cast的效果是一樣的;在進行下行轉(zhuǎn)換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。在多態(tài)類型之間的轉(zhuǎn)換主要使用dynamic_cast,因為類型提供了運行時信息。

(1)下行轉(zhuǎn)換,基類轉(zhuǎn)換為子類,例如:智能指針轉(zhuǎn)換類似于shape* 轉(zhuǎn)換為circle* 使用dynamic_cast轉(zhuǎn)換后,指針為空.此時資源還是被dptr2擁有,dptr1為0。比static_cast安全。

(2)平行轉(zhuǎn)換,指向一致的相互轉(zhuǎn)換,例如:智能指針轉(zhuǎn)換類似于circle*轉(zhuǎn)換為circle*。此時引用計數(shù)為兩者共享。

(3)上行轉(zhuǎn)換,子類轉(zhuǎn)基類,例如:智能指針轉(zhuǎn)換類似于circle*轉(zhuǎn)換為shape*,此時引用技術(shù)為兩者共享。等價于static_cast。

4.2 static_cast

同樣,編寫如下:

template<typename T, typename U>
shared_ptr static_pointer_cast(const shared_ptr &other) noexcept {
T *ptr = static_cast(other.get());
return shared_ptr(other, ptr);
}

調(diào)用:

// shape* -> circle* 使用static_cast轉(zhuǎn)換后,指針為空  與dynamic_cast相比,不安全
shared_ptr sptr2(new shape);
shared_ptr sptr1 = static_pointer_cast(sptr2); // 基類轉(zhuǎn)子類

cout << "use count of sptr1 is now " << dptr1.use_count() << endl; // 0
cout << "use count of sptr2 is now " << dptr2.use_count() << endl; // 1

// circle* -> circle* 使用dynamic_cast轉(zhuǎn)換后,指針不為空,此時資源被兩者共同使用,引用計數(shù)為2
shared_ptr sptr3(new circle);
// shared_ptr sptr3(new circle); // 上面或者當前行,后面輸出一樣!
shared_ptr sptr1_1 = static_pointer_cast(sptr3); // 基類轉(zhuǎn)子類

cout << "use count of sptr1_1 is now " << sptr1_1.use_count() << endl; // 2
cout << "use count of sptr3 is now " << sptr3.use_count() << endl; // 2

// circle* -> circle* 使用static_cast轉(zhuǎn)換后,指針不為空,此時資源被兩者共同使用,引用計數(shù)為2 等價于dynamic_cast
shared_ptr sptr3_1(new circle);
shared_ptr sptr2_1 = static_pointer_cast(sptr3_1); // 子類轉(zhuǎn)基類 上行轉(zhuǎn)換,安全!

cout << "use count of sptr2_1 is now " << sptr2_1.use_count() << endl; // 2
cout << "use count of sptr3_1 is now " << sptr3_1.use_count() << endl; // 2

輸出結(jié)果同上dynamic_cast,不同之處,在下行轉(zhuǎn)換的時候(基類轉(zhuǎn)子類),是不安全的!

4.3 const_cast

去掉const屬性:

template<typename T, typename U>
shared_ptr const_pointer_cast(
const shared_ptr &other) noexcept {
T *ptr = const_cast(other.get());
return shared_ptr(other, ptr);
}

調(diào)用:

shared_ptr s = const_pointer_cast(shared_ptr<const circle>(new circle));

4.4 reinterpret_cast

例如:想把一個指針轉(zhuǎn)為整數(shù),就可以用reinterpret_cast。

template<typename T, typename U>
shared_ptr reinterpret_pointer_cast(
const shared_ptr &other) noexcept {
T *ptr = reinterpret_cast(other.get());
return shared_ptr(other, ptr);
}

調(diào)用:

int a = reinterpret_pointer_cast<int>(s);

參考自吳老師的《現(xiàn)代C++實戰(zhàn)30講》第二講。

瀏覽 83
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 无码乱伦AV| 黑人亚洲娇小videos∞| 欧美日韩AV| 黄色片免费观看| 亚洲一级黄色视频| 国产av资源网| 欧美激情视频一区| 国产精品视频你懂的| 婷婷久久五月天| 亚洲一区二区三区在线| 色三区| 日韩中文字幕永久| 免费黄色成人网站| 第一福利视频导航| 天天日天天拍| 日本成人黄色电影| 成人精品秘久久久按摩下载| 欧美男人天堂网| 69av在线观看| 91免费视频在线| 精品成人免费视频| 久草视频福利在线| 在线成人自拍| 成人国产精品秘欧美高清| 天天操操操| 亚洲一区二区av| 久久久久久毛片| 中文字幕色站| 欧美成人国产| 51精品国产午夜福利| 操比二区| 人人操人人操人人| 在线国产中文字幕| 久草视频免费在线观看| 中文字幕+乱码+中文乱码91在线观看 | 黑人干亚洲| 久久黄视频| 欧美亚洲成人电影| 亚洲欧洲日本在线| 亚洲人人色| 精品免费| 天天天做夜夜夜夜爽无码| 久久aaaa| 日韩毛片网| 国产视频一区二区在线| 欧美午夜影院| 欧美一级婬片AAAA毛片| 伊人乱伦| 国产一区二区00000视频| 黄色视频日本免费| 九色PORNY自拍视频| 国产黄在线| 一本大道DVD中文字幕| jzzijzzij亚洲成熟少妇在线观看 九色蝌蚪9l视频蝌蚪9l视频成人熟妇 | 激情久久五月天| 日本在线播放| 91精品电影18| 亚洲热在线观看| 亚洲欧美国产日韩字幕| 日本天天操| 日韩爆乳一区二区三区| 91精品久久久久久久久久久久| 中文字幕无码免费| AA片免费| 久久精彩| 久久久精品黄色网址| 亚洲精品秘一区二区三区蜜桃久| 五月天婷婷视频| а√最新版天堂中文在线| 强开小嫩苞一区二区电影| 日韩爱爱免费视频| 亚洲电影在线| 麻豆成人精品| 日本在线网站| 欧美AAAAAAAAAA特级| 熟女视频一区二区| 日日碰狠狠躁久久躁婷婷| 国产又爽又黄视频| 99色逼| 操老女人视频| a无码| 成人网站在线免费| 丰满欧美熟妇免费视频| 国产一区二区三区免费播放| 日韩免费在线观看视频| 日本不卡视频在线| 18av在线观看| 少妇超碰| 国产无码中文字幕| 亚洲中文婷婷| av在线观看中文字幕| 亚洲精品中文字幕乱码三区91 | 人人摸在线视频| 揉BBB搡BBB搡BBB| 成人黄色一级A片| 亚洲三级片免费观看| 国产成人精品a区在线观看| 国产成人综合自拍| 久久青青婷婷| 黑人无码一二三四五区| 激情导航| 女人自慰网站在线观看| 国产91在线中日| 国产激情免费| 久久久久久国产免费A片| 色香蕉视频在线观看| 天堂A片电影网站在线观看| 黄色视频在线观看免费| 久热久热| 中国熟女网站| 欧美日韩逼| 国产成人综合自拍| 在线观看国产区| 水果派成人播放无码| 影视先锋成人在线| 欧美日韩精品一区二区三区| 夜夜爽夜夜高潮夜夜爽| 91久久久久久久91| 四川BBB搡BBB爽爽爽欧美| 国产卡一卡二在线观看| 狼友视频免费| 超碰97观看| 天堂av中文字幕| 国产婬片一级A片AAA毛片AⅤ | 欧美熟妇一区二区三区| 一区二区三区精品无码| 青青草成人电影| 国产香蕉av| 日韩中文无| 97免费| 丁香五月欧美激情| 丁香五月婷婷网| 日本91视频| 久久久国产91桃色一区二区三区| 日韩精品123| 91精品一区二区| 国产成人aV| 在线观看亚洲视频| 久久精品大屁股| 日本视频网| 欧美熟女性爱视频| 中日韩中文字幕一区二区区别| 丁香花免费高清视频小说完整| 有免费的欧美操逼视频吗| 波多野结衣无码AV专区| 日韩精品极品视频在线观看免费| 一区二区三级片| 欧美精产国品一二三区别| www.婷婷色| 美腿丝袜中文字幕精品| 亚洲性爱一级片| 日本精品在线| 一级黄色视频网站| 国产色情性黄片Av网站| 人人操人人爽| 91成人毛片| 男女做爱无码| 国产精品999999| 国产伊人网| AV青青草| 麻豆av在线观看| 先锋影音AV在线| 一级A片60分钟免费看| 热99精品| 97人妻精品黄网站| 国产91无码精品秘入口| 欧美亚洲综合手机在线| A一级黄色片| 欧美一区二区三区成人| 国产一级特黄大片| 久久久视频6r| 嫩BBB搡BBBB搡BBBB-百度| 在线亚洲一区| 亚洲免费毛片| 青春草免费视频| 欧美性爱一区二区三区| 亚洲综合日韩在线| 男女嫩草视频| 国产无码AV| 加勒比在线视频| 黄色一级片免费在线观看| 成人手机在线视频| 日本一级黄色A片| 婷婷网五月天| 国产精品宾馆| 欧美一级A片在线观看| 污片网站| 日韩免费三级片| 国产性色| 欧美淫秽视频| 成人中文字幕无码| 精品丰满人妻一区二区三区免费观 | 黄色高清无码| 欧美日韩一区二区三区| 好吊视频一区二区三区红桃视频you | 女人的天堂AV在线观看| AA免费视频| av影音先锋在线| 少妇搡BBBB搡BBB搡造水多/| 91精品免费| 久草综合在线| 兔子先生和優奈玩游戲脫衣服,運氣報表優奈輸到脫精光 | 国产福利视频| 一卡二卡久久| 夜色88V精品国产亚洲| 婷婷五月天基地| 丁香五月天网站| 性无码专区| 精品一区二区三区毛片| 黄片网站入口| 男女啪啪国产| 俺也去啦WWW色官网| 怡红院av| 成人女人18女人毛片| 日韩极品在线观看| 国产三级麻豆| 噜噜噜av| 91久久国产综合久久| 人妻丝袜蕾丝高跟双飞| 欧美三级欧美三级三级| 久久男人| 激情网五月天| 加勒比DVD手机在线播放观看视频| 中文字幕H| 婷婷五月天啪啪| 超碰97在线免费观看| 先锋成人资源| 国产一区二区00000视频| 骚BBBB槡BBB槡BBB| 久久久精品欧美| 91干| 好吊一区二区三区| 婷婷在线观看免费| 免费网站观看www在线观| 草草久久久无码国产专区的优势| 91精品婷婷国产综合久久竹菊| 香蕉av在线播放| 免费在线观看Av| 久久久精品免费视频| 香蕉久久a毛片| 人妻在线你懂的| 在线观看中文字幕亚洲| 亚洲一区二区在线播放| 黄色成人在线免费观看| 日韩aaa| 亚洲播播在线视频| 久草视频播放| 国产精品TV| 91大神免费在线观看| 91成人一区二区| 欧美激情三区| 影音先锋三级| 久久天堂影院| 成人精品免费无码毛片| 天堂在线中文字幕| 黄片网址| 人妻一区二区在线| 久久久一| 在线小视频| 91麻豆一区二区| 91蜜桃传媒在线观看| 91在线日韩| 天堂A片电影网站在线观看| 日韩欧美成人网| 亚洲AV大片| 毛片一区二区三区| 丁香花中文字幕| 国产成人影视在线观看| 91免费福利| 欧洲黑人成人A版免费视频| 怡红院一区二区| 91农村站街老熟女露脸| 成人网在线视频| 久热这里只有| 中国一级黄色毛片| 亚洲国产精品视频| 丁香激情综合| 伊人色播| 国产福利AV| 狠狠撸综合| 黑人巨粗进入疼哭A片| 国产免费视频| igao在线观看| 四虎成人免费视频| 成人在线观看网站| 精品中文视频| 久久免费视频1| 91人妻成人精品一区二区| 黄色网址在线观看视频| 三级国产AV| 四虎av| 欧美va亚洲va| 激情小说五月天| 欧美精产国品一二三产品动漫| 91porn国产| 99高清无码| 亚洲777| 九九久久精品视频| 夜夜骑夜夜| 亚洲色在线播放| 97超碰成人| 五月婷丁香| 九九九九精品视频| 人人妻人人澡人人爽人人爽| 婷婷五月在线视频| 亚洲欧美成人片| 毛片毛片毛片毛片毛片| 老女人操逼视频| 地表最强网红八月未央道具大秀 | 国产性爱在线| 1204手机看片| 中文无码电影| 骚妇一区| 色天堂在线观看视频| 免费av大全| 欧美日韩大屌| 91丨PORNY丨丰满人妻网站| 中文字幕东京热加勒比| 欧美亚洲国产日韩| 黄色在线免费观看| 另类激情网| 免费操| 美女黄色视频永费在线观看网站| 免费视频A| 免费福利在线观看| 国产91丝袜在线播放| 99精品视频免费| 亚洲欧美熟妇久久久久久久久| 3D动漫精品一区二区在线播放免费| 亚洲免费视频在线| 青娱乐成人在线视频| 免费看成人A片无码照片88hⅤ | 91人妻人人澡人人澡人人精品| 浪潮在线观看完整版| 人人妻天天干| 欧美级毛片一进一出| 亚洲视频A| 国产91探花秘入口| 人妻无码HEYZO少妇精品| 欧美AAA在线观看| 黄色电影免费在线观看| 污视频网站免费在线观看| 国产在线视频你懂的| 亚洲va欧美ⅴa在线| 色婷婷日韩精品一区二区三区| 天堂麻豆天美| 日韩无码五月天| 91就要爱爱视频| 九九九欧美| 欧美三级片视频| 国产91久久婷婷一区二区| 亚洲精品高清无码| 美女被操面费网站| 91精品国自产在线观看| 91网站在线免费观看| 黄色视频在线免费播放| 欧美精品一区二区三区蜜臀| 日韩黄色三级| 欧美性BBwBBwBBwHD| 欧美第二页| 日韩无任何视频在线观看| 思思热思思操| 乱码中文字幕日韩欧美在线| 欧美精品性爱视频| 俺去也| 五月婷婷网| 亚洲女人天堂| 免费无码国产在线55| 少妇做爱视频| 久久免费视频,久久免费视频| 久久久久久久国产| 国产精品每日更新| 中文字幕精品无码亚| 久本草精品| 中文字幕综合网| 日韩专区在线观看| 色墦五月丁香| 国产精品一区二区三区在线| 91视频免费看| 免费看黄在线看| 人人操碰成人网| 黄色在线免费观看网站| 老司机AV91| 中文有码在线观看| 亚洲人视频| 国产a毛片| 人人人妻人人人操| www.男人天堂| 青青国产在线观看| 毛片毛片毛片毛片| 白天操夜夜操| 五月婷婷丁香五月| 免费性片| 日韩经典视频在线播放| 免费欧美性爱| 中文字幕一区三区三A片密月| 在线亚洲小视频| 日韩中文字幕无码人妻| 台湾成人视频| 色呦呦视频| 午夜在线视频| 日本人妻在线观看| 乱伦精品| 潮喷在线观看| 国外亚洲成AV人片在线观看| 日韩a级片| 人妻少妇精品视频一区二区三区| 99热自拍| 2019天天操| 91精品国产综合久久久久久| 亚洲欧美视频一区| 性色aV中文字幕| 91干干干| 午夜精品18视频国产| 成人小说在线观看| 操逼视频在线免费看| 91传媒在线观看| 亚洲AV无码成人专区| 肥臀AV在线| 久久久久婷婷| 国产精品7777| 亚洲精品黄色| 一级欧美黑人大战白妞| 久久精品综合| 中文字幕AⅤ在线| 熟女视频网| 内射少妇18| 自拍视频一区| 黄色av无码| 色五月婷婷综合| 日韩中文无码电影| 噜噜视频| 一级a免一级a做免费线看内裤的注意事项| 免费看一级高潮毛片| 天天肏夜夜肏| 精品视频免费在线观看| 爱搞视频在线观看| 久久久久久久免费| 白峰美羽人妻AND-499| 97人人爱| 天天色色天天| 色秘乱码一区二区三区| 18禁网站禁片免费观看| 久久五月天综合| 91女人18毛片水多国产| 亚洲三级在线视频| 强开小嫩苞毛片一二三区| 久操视频免费观看| AV色天堂| 国产精品91久久久| 人人操大香蕉| 欧美成人网站免费在线观看| 久久亚洲中文字幕乱码| 97超碰资源| 午夜福利无码电影| 大香蕉在线视频99| 黄色特级毛片| 亚洲国产综合AV在线| 亚洲欧洲在线视频| 色综合中文字幕| 亚洲不卡视频| 欧美久久视频| 好看的中文字幕av| 黄色小电影在线观看| 亚洲乱伦电影| 日本人妻在线播放| 黄色免费网站在线观看| 亚洲精品乱码久久久久久| 好逼天天操| 91视频亚洲| 撸久久| 大香蕉久久精品| 18禁网址| 精品自拍偷拍| 午夜天堂在线| 国产換妻4P视频| 麻豆mdapp03.tⅴ| 欧美精品乱码99久久蜜桃| 亚洲青草视频| 国产在线视频你懂的| 日产精品久久久一区二区| 一区二区精品视频| 亚洲成人高清无码| AV无码免费一区二区三区不卡| 日韩无码波多野结衣| 日本免费爱爱视频| 艳妇乳肉豪妇荡乳AV无码福利| 2024男人天堂| 亚洲视频在线播放| 中文字幕黄色电影| 噜噜噜久久久| h在线观看h| 五月天婷婷视频| 五月婷婷六月丁香综合| 欧美视频自拍| 91就要爱爱视频| av自拍| 天天干天天射天天爽| 自拍偷拍一区二区三区| 色婷婷基地| 一道本一区二区三区| 97人妻人人| 欧美亚洲色色网视频| 欧美视频精品| 一本色道久久综合无码| 黄色av网| 伊人青草视频9| 四虎黄色网址| 福利网址| 免费在线a视频| 色骚爽大香蕉91| 中文字幕在线观看AV| 在线视频一区二区三区四区| 日韩AV网站在线观看| 午夜毛片| 欧美视频免费在线观看| 人成免费在线视频| 日本中文无码| 欧美日韩免费在线播放电影在线播放电影在线播放电影免费 | 国产www在线观看| 中文字幕在线观看日本| 久久五月天综合| 亚洲成人福利在线| 成人做爰A片一区二区app| 国产无套内射视频| 91av一区二区三区| 豆花成人在线| 在线观看中文字幕av| 天天色影| 成人理伦A级A片在线论坛| 国内精品人妻无码久久久影院蜜桃 | 日本三级AAA三级AAAA97| 日韩成人中文字幕| 国产AV一二三区| 最近日本中文字幕中文翻译歌词| 人操人人人操| 大香蕉欧美| 人人插人人干| 亚洲精品69| 黄色免费视频| 国产一级a毛片| 日韩AAA| 波多野结衣视频在线| 免费视频久久| 人妻啪啪| 久久久一级| 欧美一级a| 日本色色色| 99热3| 中文字幕第23页| 日夜夜操| 亚洲一区欧美二区gay| 蜜桃av秘无码一区二区| 免费黄片视频在线观看| 国产Av影视| 亚洲一本大道| 欧美精品无码久久久精品酒店 | 亚洲成人自拍无码| 西西444WWW大胆无| 成人在线精品视频| 9l视频自拍蝌蚪9l成人蝌蚪| 在线观看视频你懂的| 噼里啪啦免费观看视频大全| 国产和日韩中文字幕| 亚洲插逼| 欧美日韩成人视频| 国产第56页| 婷婷精品免费| 免费看黄视频| 99九九99九九九99九他書對| 国产AV影院| 黄色录像一级片| 在线免费观看无码| 久久九九热| 日韩成人不卡| 美女少妇激情BBBB| 久久毛久久久j| 日日撸夜夜撸| 久久久福利视频| 欧洲成人在线视频| 欧美一级欧美三级在线观看| 日韩性爱一区| 中文资源在线√8| 水果派解说A∨无码区| 91麻豆精品| 亚洲色综合| 婷婷五月天国产| 亚欧成人网站| 国产亲子乱XXXXimim/| 国产黄片在线视频| 老熟女--91XX| 日日操天天操夜夜操| 青青操在线视频| 国产电影一区二区三区| 丁香六月综合| 久操视频在线观看免费| 国产av一区二区三区四区| 北条麻妃青青久久| 国产精品伦子伦免费视频| 黑人av在线观看| 韩日一级17c| 97无码视频| 手机免费AV| 豆花视频成人精品视频| 国产一级婬片A片免费无成人黑豆 国产真实露脸乱子伦对白高清视频 | 亚洲AV成人无码精品| 国产人妻AV| 99色热视频| 国产搡BBB爽爽爽视频| 蜜桃av秘无码一区二区三| 亚洲天堂视频在线观看| 青青操在线观看| 久久久国产91桃色一区二区三区| 久久久久黄色| 一道本一区二区三区| 日韩无码成人片| 国产乱人伦无码视频| 九九精品免费视频| 2024无码| 欧美干综合| 国产麻豆精品ThePorn| 北条麻妃久久视频在线播放| 亚洲成人黄色电影| 五月丁香综合网| 91人妻人人澡| 国产三级网| 无码不卡在线观看| 夜夜操网站| 午夜福利aaa| 日韩一片| 日韩av高清| 高清无码爱爱| 丁香六月婷婷综合激情欧美| 一级黄色电影免费在线观看| 国产又粗又大又爽| 一本色道久久88亚洲精品综合| 国产精品成人69| 久久er视频| 在线免费观看国产| 日韩无码人妻久久一区二区三区| 蜜桃视频在线观看18| 欧美成人毛片| 91嫩草欧美久久久九九九| www.av在线| 大香蕉中文| 蜜桃av秘无码一区二区三区| 男人网站| 欧美三级欧美一级| 成人亚洲AV日韩AV无码| 日韩AV中文字幕在线| 日韩大香蕉在线| 成人欧美精品区二区三| XXXXⅩHD亚洲人HD| 亲子伦视频一区二区三区| 免费在线观看无码视频| 91丨九色丨国产在线| 日韩天堂在线观看| H片免费在线观看| 午夜福利电影网| 亚洲男女免费视频| 人妻少妇精品无码| 俺也来www俺也色com| 亚洲天堂男人天堂| 青青草公开视频| 无码人妻在线播放| 黄片大全在线免费观看| 在线观看的AV| 日本一级婬片免费放| 人人超碰人人| 成人黄色小电影| 99久久久精品| 亚洲国产精品二二三三区| 狠狠干伊人| 国产精品秘久久久久久1-~/\v7-/ 囯产精品一区二区三区线一牛影视1 | 日韩成人综合| 丁香五月欧美| AAA黄片| 亚洲无码视频免费观看| 国产一级黄色| 久草视频在线播放| 91在线视频观看| 国产色五月视频| 日韩视频免费观看高清完整版在线观| 极品小仙女69| 精品中文字幕在线播放| 国产AV日韩AⅤ亚洲AV中文 | 一本色道久久综合无码欧美| 国产女人18毛片精品18水| 懂色av,蜜臀AV粉嫩av| 日本午夜福利电影| 天天日天天舔| 在线观看亚洲视频| 亚洲三级在线观看| 成人免费视频性爱| 五月六月丁香激情视频| 人人操人人摸人人射| 亚韩在线| 色婷婷AV在线观看| 国产精久久| 青青草网址| 先锋成人av| 国产av资源网| 又黄又爽的网站| 8x8x黄色| 免费AA片| 小處女末发育嫩苞AV| 成人无码中文字幕| 男女操逼网站| 最新中文字幕一区| 人妻超碰在线| 狠狠操狠狠插| 亚洲av大片| 少婦揉BBBB揉BBBB揉| 老司机一区二区| 国产三级片无码| 在线观看的av网站| 日本中文字幕在线播放| 北条麻妃无码视频在线观看| www.狠狠| 嫩BBB槡BBBB槡BBBB撒尿-百度 | 亚洲va欧美va天堂v国产综合 | 国产色婷婷精品综合在线播放| 亚洲AV毛片| 人妖黃色一級A片| 久久在线免费视频| 欧美成人网站视频| 亚洲自拍小说| 久久在线视频| 182AV| 一区二区三区无码在线| 99热在线观看精品| 亚洲成人免费在线观看| 欧美一级片免费看| 午夜精品电影| 黄色网址五月天| 97大香蕉视频| 日本一区二区三区四区| 在线视频日本| 成人资源站| 欧美日韩视频在线播放| 日区无码| 欧美成人天堂| 妖精视频黄色| 手机在线观看av| 97色在线视频| 潮喷av| 操逼视频91| 午夜精品18| 精品视频免费在线| 99热99| 青青免费在线视频| 亚洲成人一区| 91成人在线播放| 在线观看国产欧美| 妻子互换被高潮了三次| 国产精品无| 天天日天天舔| 国产人妖TS重口系列网站观看| 香蕉国产AV| 天天色影| 国产无码午夜| 精品无码秘人妻一区二区三区| 欧美一级特黄真人做受| 中文毛片| 天天中文字幕| 在线日韩中文字幕| 国产在线高潮| 大香蕉大香蕉免费网| 唐山熟女工棚嗷嗷叫| 亚洲色色色| 欧美一级操| 五月香婷婷| 国精产品一区一区三区有限公司杨| 国产AV天堂| 日韩欧美手机在线| 91AV一区二区三区| 天天色天天干天天日| 在线观看www视频| 国产免费一区二区三区四区| 欧美日韩一区在线| 狠狠色噜噜狠狠狠888米奇视频| MAD033_后宫秘密陶子.| 肉乳无码A片av| 72成人网| 国产亚洲99久久精品| 天天干夜夜骑| 九九精品视频在线播放| 日韩色情电影| 久久视频一二| 成人在线精品| 黄片大全在线免费观看| 久久久久人| 五月天中文字幕| 日本大香蕉伊人| 揉BBB搡BBB搡BBB| 亚洲综合区| 91精品国产偷窥一区二区| WWW.亚洲无码| 性爱无码AV| 人妻无码中文字幕免费视频蜜桃| 国产女人18毛片水真多1| 黄色一级大片在线免费看产| 淫秽视频免费看| 香蕉操逼视频| 三级成人在线| 成人水蜜桃| 神马午夜精品96| 无码伊人| 无码熟妇人妻无码AV在线天堂| 亚洲AV无码成人精品区天堂小说 | 婷婷色大师| 高清无码视频网站| 蜜桃Av噜噜一区二区三| 久久视频在线| 女人高潮天天躁夜夜躁| 毛片福利| 欧美老熟女18| 亚洲AV成人片色在线观看高潮| 免费的黄色A片| 国产精品无码永久免费不卡| 翔田千里在线播放| 天天干婷婷五月天| 亚洲AV无码成人精品区天堂小说 | 国产一级a毛一级a毛观看视频网站www.jn | 日韩顶级毛片| 黄色一级录像| 先锋影音中文字幕| 国产三级精品三级在线观看| 亚洲偷拍中文| 欧美成人一区二区三区| 欧美日韩高清无码| 嫩BBB| 亚洲伊人影院| 无码人妻丰满熟妇精品区| 少妇大战黑人46厘米| 超碰99热| AV无码一区二区| 六十路老熟女码视频| 奇米超碰| 99热视| 肏屄视频免费观看| 熟妇女人妻丰满少妇中文字幕| 亚洲免费观看高清完| 操日视频| 精品夜夜澡人妻无码AV| 东京热视频网| 怡红院欧美| 国产成人无码精品| 蜜桃免费| 热久久在线| 中文字幕一区三区三A片密月| 91人妻人人澡人人爽人| 三级片无码视频| 欧美性爱福利视频| 日日搔av一区二区三区| 国产在线性爱视频| 亚洲色成人中文字幕在线| 97这里只有精品| 婷婷亚洲综合| 国产精品你懂的| 草逼小视频| 国产原创精品| 天堂一区二区18| 桃花岛tⅴ+亚洲品质| 中文字幕东京热| 国产成人tv| 午夜亚洲AV永久无码精品蜜芽| 久久久天堂国产精品女人| 特级西西人体WWWww| 天堂成人在线| 国产无套内射在线观看| 久久久久久婷婷| 久久这里只有精品9| 美女网站黄色| 亚洲一区二区久久| 欧美日韩北条麻妃视频在线观看| 未满十八18禁止免费无码网站| 欧美69| 精品无码一区二区人妻久久蜜桃| 午夜成人福利| 欧美色图在线视频| 日韩特黄| 高h视频在线观看| 国产一区二区视频在线观看| 欧美精品成人免码在线| 一区二区三区免费在线| 中文字幕在线免费播放| 亚洲免费观看高清完整版| 久久一道| 大香蕉老师| 草草浮力院| 中文字幕日本无码| 天天中文字幕| 人人摸人人操人人干| 91人妻无码精品一区二区三区| 国产伊人网| 日韩日韩日韩| 亚洲第一综合| 色哟哟在线观看| 国产精品无码在线播放|