日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
手?jǐn)]一個智能指針,你學(xué)會了嗎?

估計大家面試過程中應(yīng)該都會被問到C++11的shared_ptr是如何實現(xiàn)的,大家應(yīng)該都能答出來引用計數(shù)的概念,但是如果要讓你手寫一個shared_ptr,你能寫出來嗎?

創(chuàng)新互聯(lián)公司長期為超過千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為洮南企業(yè)提供專業(yè)的網(wǎng)站設(shè)計、成都做網(wǎng)站,洮南網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

最近,我寫了一個簡單的shared_ptr,在這里分享一波。

首先定義一個主管引用計數(shù)的類:

class SharedCount {
public:
SharedCount() : count_{1} {}

void add() { ++count_; }

void minus() { --count_; }

int get() const { return count_; }

private:
std::atomic count_;
};

然后就是SharedPtr類,首先在構(gòu)造函數(shù)中創(chuàng)建SharedCount的對象:

template 
class SharedPtr {
public:
SharedPtr(T* ptr) : ptr_{ptr}, ref_count_{new SharedCount} {}

SharedPtr() : ptr_{nullptr}, ref_count_{new SharedCount} {}

private:
T* ptr_;
SharedCount* ref_count_;
};

通過構(gòu)造函數(shù)創(chuàng)建出來的SharedPtr引用計數(shù)肯定是1,那析構(gòu)函數(shù)怎么實現(xiàn)?無非就是將引用計數(shù)減1,如果引用計數(shù)最終減到0,則釋放所有指針:

template 
class SharedPtr {
public:
~SharedPtr() { clean(); }

private:
void clean() {
if (ref_count_) {
ref_count_->minus();
if (ref_count_->get() == 0) {
if (ptr_) delete ptr_;
delete ref_count_;
}
}
}
};

然后就是智能指針的關(guān)鍵部分,即在拷貝構(gòu)造和拷貝賦值的時候?qū)⒁糜嫈?shù)+1:

template 
class SharedPtr {
public:
SharedPtr(const SharedPtr& p) {
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
ref_count_->add();
}

SharedPtr& operator=(const SharedPtr& p) {
clean();
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
ref_count_->add();
return *this;
}
};

處理了拷貝語義,還需要處理移動語義,即實現(xiàn)移動構(gòu)造和移動賦值函數(shù):

template 
class SharedPtr {
public:
SharedPtr(SharedPtr&& p) {
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
p.ptr_ = nullptr;
p.ref_count_ = nullptr;
}

SharedPtr& operator=(SharedPtr&& p) {
clean();
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
p.ptr_ = nullptr;
p.ref_count_ = nullptr;
return *this;
}
};

在移動語義中,引用計數(shù)保持不變,同時清空原參數(shù)中的指針。

關(guān)于共享指針,到這里基本邏輯都已經(jīng)實現(xiàn)完成,但還需要補充獲取裸指針、獲取引用計數(shù)等接口:

這樣一個完整的智能指針大體已經(jīng)實現(xiàn)完成,運行一下看看:

struct A { A() { std::cout << "A() \n"; } ~A() { std::cout << "~A() \n"; }};void test_simple_shared() { A* a = new A; SharedPtr ptr(a); { std::cout << ptr.use_count() << std::endl; SharedPtr b = ptr; std::cout << ptr.use_count() << std::endl; SharedPtr c = ptr; std::cout << ptr.use_count() << std::endl; SharedPtr d = std::move(b); std::cout << ptr.use_count() << std::endl; } std::cout << ptr.use_count() << std::endl;}int main() { test_simple_shared(); }

結(jié)果為:

template 
class SharedPtr {
public:
int use_count() { return ref_count_->get(); }

T* get() const { return ptr_; }

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

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

operator bool() const { return ptr_; }

private:
T* ptr_;
SharedCount* ref_count_;
};

基本的shared_ptr完成后,再來寫點有意思的,不知道大家有沒有用過這幾個指針轉(zhuǎn)換函數(shù):

struct A {
A() { std::cout << "A() \n"; }
~A() { std::cout << "~A() \n"; }
};

void test_simple_shared() {
A* a = new A;
SharedPtr ptr(a);
{
std::cout << ptr.use_count() << std::endl;
SharedPtr
b = ptr;
std::cout << ptr.use_count() << std::endl;
SharedPtr
c = ptr;
std::cout << ptr.use_count() << std::endl;
SharedPtr
d = std::move(b);
std::cout << ptr.use_count() << std::endl;
}
std::cout << ptr.use_count() << std::endl;
}

int main() { test_simple_shared(); }

結(jié)果為:

A()
1
2
3
3
1
~A()

基本的shared_ptr完成后,再來寫點有意思的,不知道大家有沒有用過這幾個指針轉(zhuǎn)換函數(shù):

template
std::shared_ptr static_pointer_cast(const std::shared_ptr& r) noexcept;

template
std::shared_ptr const_pointer_cast(const std::shared_ptr& r) noexcept;

template
std::shared_ptr dynamic_pointer_cast(const std::shared_ptr& r) noexcept;

template
std::shared_ptr reinterpret_pointer_cast(const std::shared_ptr& r) noexcept;

我默認(rèn)大家已經(jīng)知道這幾個函數(shù)的作用,這里直接研究一下它的實現(xiàn):

template 
class SharedPtr {
public:
private:
template
SharedPtr(const SharedPtr& p, T* ptr) {
this->ptr_ = ptr;
this->ref_count_ = p.ref_count_;
ref_count_->add();
}

T* ptr_;
SharedCount* ref_count_;
};

template
SharedPtr static_pointer_cast(const SharedPtr& p) {
T* ptr = static_cast(p.get());
return SharedPtr(p, ptr);
}

SharedPtr和SharedPtr不是一個類,所以上面的代碼會稍微有點問題,p無法訪問它的private成員變量ref_count,那怎么解決呢?上友元:

template 
class SharedPtr {
public:
template
friend class SharedPtr;
};

上面的代碼還是有問題,因為SharedPtr(const SharedPtr& p, T* ptr)是private,static_pointer_cast無法訪問,有兩種辦法,一是變成public,二是友元,這里還是友元更合理些,添加友元后的代碼如下:

template 
class SharedPtr {
public:
template
friend class SharedPtr;

template
friend SharedPtr static_pointer_cast(const SharedPtr& p);

private:
template
SharedPtr(const SharedPtr& p, T* ptr) {
this->ptr_ = ptr;
this->ref_count_ = p.ref_count_;
ref_count_->add();
}

T* ptr_;
SharedCount* ref_count_;
};

template
SharedPtr static_pointer_cast(const SharedPtr& p) {
T* ptr = static_cast(p.get());
return SharedPtr(p, ptr);
}

再測試一下:

struct A {
A() { std::cout << "A() \n"; }
~A() { std::cout << "~A() \n"; }
};

struct B : A {
B() { std::cout << "B() \n"; }
~B() { std::cout << "~B() \n"; }
};

void test_cast_shared() {
B* a = new B;
SharedPtr ptr(a);
{
std::cout << ptr.use_count() << std::endl;
SharedPtr
b = static_pointer_cast(ptr);
std::cout << ptr.use_count() << std::endl;
SharedPtr c = ptr;
std::cout << ptr.use_count() << std::endl;
SharedPtr d = ptr;
std::cout << ptr.use_count() << std::endl;
}
std::cout << ptr.use_count() << std::endl;
}

int main() { test_cast_shared(); }

結(jié)果為:

A()
B()
1
2
3
4
1
~B()
~A()

上面只實現(xiàn)了static_pointer_cast,其他xxx_pointer_cast的原理類似,大家應(yīng)該也明白了吧。

C++還有個unique_ptr,這個相對于shared_ptr就簡單多了,表示unique語義,沒有引用計數(shù)的概念,因為不允許拷貝,原理就是禁止調(diào)用拷貝構(gòu)造函數(shù)和拷貝賦值函數(shù),直接貼代碼吧:

template 
class UniquePtr {
public:
UniquePtr(T* ptr) : ptr_{ptr} {}

UniquePtr() : ptr_{nullptr} {}

UniquePtr(const UniquePtr& p) = delete;
UniquePtr& operator=(const UniquePtr& p) = delete;

UniquePtr(UniquePtr&& p) {
this->ptr_ = p.ptr_;
p.ptr_ = nullptr;
}

UniquePtr& operator=(UniquePtr&& p) {
clean();
this->ptr_ = p.ptr_;
p.ptr_ = nullptr;
return *this;
}

T* get() const { return ptr_; }

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

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

operator bool() const { return ptr_; }

~UniquePtr() { clean(); }

private:
void clean() {
if (ptr_) delete ptr_;
}

T* ptr_;
};

重點其實只有這兩個delete:

template 
class UniquePtr {
public:
UniquePtr(const UniquePtr& p) = delete;
UniquePtr& operator=(const UniquePtr& p) = delete;
};

到這里已經(jīng)實現(xiàn)了一個簡單的shared_ptr和unique_ptr,希望對大家有所幫助,完整代碼見這里:

??https://github.com/chengxumiaodaren/cpp-learning/blob/master/src/test_shared_ptr.cc??


文章題目:手?jǐn)]一個智能指針,你學(xué)會了嗎?
當(dāng)前網(wǎng)址:
http://m.5511xx.com/article/ccsohsh.html