日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

C++11中weak_ptr的使用

發(fā)布時(shí)間:2023/11/27 生活经验 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++11中weak_ptr的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在C++中,動(dòng)態(tài)內(nèi)存的管理是通過(guò)一對(duì)運(yùn)算符來(lái)完成的:new,在動(dòng)態(tài)內(nèi)存中為對(duì)象分配空間并返回一個(gè)指向該對(duì)象的指針,可以選擇對(duì)對(duì)象進(jìn)行初始化;delete,接受一個(gè)動(dòng)態(tài)對(duì)象的指針,銷毀該對(duì)象,并釋放與之關(guān)聯(lián)的內(nèi)存。

動(dòng)態(tài)內(nèi)存的使用很容易出問(wèn)題,因?yàn)榇_保在正確的時(shí)間釋放內(nèi)存是極其困難的。有時(shí)會(huì)忘記釋放內(nèi)存,在這種情況下會(huì)產(chǎn)生內(nèi)存泄露;有時(shí)在尚有指針引用內(nèi)存的情況下就釋放了它,在這種情況下就會(huì)產(chǎn)生引用非法內(nèi)存的指針。

為了更容易(同時(shí)也更安全)地使用動(dòng)態(tài)內(nèi)存,C++11標(biāo)準(zhǔn)庫(kù)提供了兩種智能指針(smart pointer)類型來(lái)管理動(dòng)態(tài)對(duì)象。智能指針的行為類似常規(guī)指針,重要的區(qū)別是它負(fù)責(zé)自動(dòng)釋放所指的對(duì)象。C++11標(biāo)準(zhǔn)庫(kù)提供的這兩種智能指針的區(qū)別在于管理底層指針的方式:shared_ptr允許多個(gè)指針指向同一個(gè)對(duì)象;unique_ptr則"獨(dú)占"所指向的對(duì)象。C++11標(biāo)準(zhǔn)庫(kù)還定義了一個(gè)名為weak_ptr的輔助類,它是一種弱引用,指向shared_ptr所管理的對(duì)象。這三種類型都定義在memory頭文件中。智能指針是模板類而不是指針。類似vector,智能指針也是模板,當(dāng)創(chuàng)建一個(gè)智能指針時(shí),必須提供額外的信息即指針可以指向的類型。默認(rèn)初始化的智能指針中保存著一個(gè)空指針。智能指針的使用方式與普通指針類似。解引用一個(gè)智能指針?lè)祷厮赶虻膶?duì)象。如果在一個(gè)條件判斷中使用智能指針,效果就是檢測(cè)它是否為空。

Pointer misuse can be a major source of bugs. Smart pointers prevent most situations of memory leaks by making the memory deallocation automatic. More generally, they make object destruction automatic: an object controlled by a smart pointer is automatically destroyed (finalized and then deallocated) when the last (or only) owner of an object is destroyed.

In C++, a smart pointer is implemented as a template class that mimics, by means of operator overloading, the behaviors of a traditional (raw) pointer, while providing additional memory management features.

std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to assume temporary ownership. If the original std::shared_ptr is destroyed at this time,the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.

In addition,std::weak_ptr is used to break circular references of std::shared_ptr.

weak_ptr is primarily useful in the rare cases where it is needed in order to break'circular references' – a problem with the use of reference counting in shared_ptr.

Sometimes an object must store a way to access the underlying object of a shared_ptr without causing the reference count to be incremented. Typically, this situation occurs when you have cyclic references between shared_ptr instances. The best design is to avoid shared ownership of pointers whenever you can. However, if you must have shared ownership of shared_ptr instances, avoid cyclic references between them. When cyclic references are unavoidable, or even preferable for some reason, use weak_ptr to give one or more of the owners a weak reference to another shared_ptr. By using a weak_ptr, you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero. However, you can use a weak_ptr to try to obtain a new copy of the shared_ptr with which it was initialized. If the memory has already been deleted, a bad_weak_ptr exception is thrown. If the memory is still valid, the new shared pointer increments the reference count and guarantees that the memory will be valid as long as the shared_ptr variable stays in scope.

weak_ptr被設(shè)計(jì)為與shared_ptr共同工作,可以從一個(gè)shared_ptr或者另一個(gè)weak_ptr對(duì)象構(gòu)造,獲得資源的觀測(cè)權(quán)。但weak_ptr沒(méi)有共享資源,它的構(gòu)造不會(huì)引起指針引用計(jì)數(shù)的增加。同樣,在weak_ptr析構(gòu)時(shí)也不會(huì)導(dǎo)致引用計(jì)數(shù)的減少,它只是一個(gè)靜靜地觀察者。weak_ptr沒(méi)有重載operator*和->,這是特意的,因?yàn)樗还蚕碇羔?#xff0c;不能操作資源,這是它弱的原因。但它可以使用一個(gè)非常重要的成員函數(shù)lock()從被觀測(cè)的shared_ptr獲得一個(gè)可用的shared_ptr對(duì)象,從而操作資源。

weak_ptr用于解決”引用計(jì)數(shù)”模型循環(huán)依賴問(wèn)題,weak_ptr指向一個(gè)對(duì)象,并不增減該對(duì)象的引用計(jì)數(shù)器。weak_ptr用于配合shared_ptr使用,并不影響動(dòng)態(tài)對(duì)象的生命周期,即其存在與否并不影響對(duì)象的引用計(jì)數(shù)器。weak_ptr并沒(méi)有重載operator->和operator *操作符,因此不可直接通過(guò)weak_ptr使用對(duì)象。weak_ptr提供了expired()與lock()成員函數(shù),前者用于判斷weak_ptr指向的對(duì)象是否已被銷毀,后者返回其所指對(duì)象的shared_ptr智能指針(對(duì)象銷毀時(shí)返回”空”shared_ptr)。

智能指針是模板類而不是指針.

weak_ptr并沒(méi)有重載operator->和operator *操作符,因此不可直接通過(guò)weak_ptr使用對(duì)象,典型的用法是調(diào)用其lock函數(shù)來(lái)獲得shared_ptr示例,進(jìn)而訪問(wèn)原始對(duì)象。

weak_ptr是一種不控制所指向?qū)ο笊嫫诘闹悄苤羔?#xff0c;它指向由一個(gè)shard_ptr管理的對(duì)象。將一個(gè)weak_ptr綁定到一個(gè)shared_ptr不會(huì)改變shared_ptr的引用計(jì)數(shù)。一旦最后一個(gè)指向?qū)ο蟮膕hared_ptr被銷毀,對(duì)象就會(huì)被釋放。即使有weak_ptr指向?qū)ο?#xff0c;對(duì)象也還是會(huì)被釋放。

當(dāng)創(chuàng)建一個(gè)weak_ptr時(shí),要用一個(gè)shared_ptr來(lái)初始化它。不能使用weak_ptr直接訪問(wèn)對(duì)象,而必須調(diào)用lock。此函數(shù)檢查weak_ptr指向的對(duì)象是否仍存在。如果存在,lock返回一個(gè)指向共享對(duì)象的shared_ptr。與任何其它shared_ptr類似,只要此shared_ptr存在,它所指向的底層對(duì)象也就會(huì)一直存在。

下圖列出了weak_ptr支持的操作(來(lái)源于C++ Primer Fifth Edition 中文版):


下面是從其他文章中copy的測(cè)試代碼,詳細(xì)內(nèi)容介紹可以參考對(duì)應(yīng)的reference:
#include "weak_ptr.hpp"
#include <iostream>
#include <memory>
#include <algorithm>
#include <string>
#include <vector>///
// reference: http://en.cppreference.com/w/cpp/memory/weak_ptr
std::weak_ptr<int> gw;void f()
{if (auto spt = gw.lock()) { // Has to be copied into a shared_ptr before usagestd::cout << *spt << "\n";}else {std::cout << "gw is expired\n";}
}int test_weak_ptr1()
{{auto sp = std::make_shared<int>(42);gw = sp;f();}f();return 0;
}/
// reference: http://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful
int test_weak_ptr2()
{// OLD, problem with dangling pointer// PROBLEM: ref will point to undefined data!int* ptr = new int(10);int* ref = ptr;delete ptr;// NEW// SOLUTION: check expired() or lock() to determine if pointer is valid// empty definitionstd::shared_ptr<int> sptr;// takes ownership of pointersptr.reset(new int);*sptr = 10;// get pointer to data without taking ownershipstd::weak_ptr<int> weak1 = sptr;// deletes managed object, acquires new pointersptr.reset(new int);*sptr = 5;// get pointer to new data without taking ownershipstd::weak_ptr<int> weak2 = sptr;// weak1 is expired!if (auto tmp = weak1.lock())std::cout << *tmp << '\n';elsestd::cout << "weak1 is expired\n";// weak2 points to new data (5)if (auto tmp = weak2.lock())std::cout << *tmp << '\n';elsestd::cout << "weak2 is expired\n";return 0;
}//
// reference: https://msdn.microsoft.com/en-us/library/hh279672.aspx
class Controller
{
public:int Num;std::string Status;std::vector<std::weak_ptr<Controller>> others;explicit Controller(int i) : Num(i), Status("On"){std::cout << "Creating Controller" << Num << std::endl;}~Controller(){std::cout << "Destroying Controller" << Num << std::endl;}// Demonstrates how to test whether the pointed-to memory still exists or not.void CheckStatuses() const{for_each(others.begin(), others.end(), [](std::weak_ptr<Controller> wp) {try {auto p = wp.lock();std::cout << "Status of " << p->Num << " = " << p->Status << std::endl;}catch (std::bad_weak_ptr b) {std::cout << "Null object" << std::endl;}});}
};void RunTest()
{std::vector<std::shared_ptr<Controller>> v;v.push_back(std::shared_ptr<Controller>(new Controller(0)));v.push_back(std::shared_ptr<Controller>(new Controller(1)));v.push_back(std::shared_ptr<Controller>(new Controller(2)));v.push_back(std::shared_ptr<Controller>(new Controller(3)));v.push_back(std::shared_ptr<Controller>(new Controller(4)));// Each controller depends on all others not being deleted.// Give each controller a pointer to all the others. for (int i = 0; i < v.size(); ++i) {for_each(v.begin(), v.end(), [v, i](std::shared_ptr<Controller> p) {if (p->Num != i) {v[i]->others.push_back(std::weak_ptr<Controller>(p));std::cout << "push_back to v[" << i << "]: " << p->Num << std::endl;}});}for_each(v.begin(), v.end(), [](std::shared_ptr<Controller>& p) {std::cout << "use_count = " << p.use_count() << std::endl;p->CheckStatuses();});
}int test_weak_ptr3()
{RunTest();std::cout << "Press any key" << std::endl;char ch;std::cin.getline(&ch, 1);return 0;
}// reference: https://oopscenities.net/2014/08/03/c-smart-pointers-part-5-weak_ptr/
struct Child;
struct Parent
{std::shared_ptr<Child> child;~Parent() { std::cout << "Bye Parent" << std::endl; }void hi() const { std::cout << "Hello" << std::endl; }
};struct Child
{std::weak_ptr<Parent> parent;//std::shared_ptr<Parent> parent; // memory leak~Child() { std::cout << "Bye Child" << std::endl; }
};int test_weak_ptr4()
{auto parent = std::make_shared<Parent>();auto child = std::make_shared<Child>();parent->child = child;child->parent = parent;child->parent.lock()->hi();// child->parent->hi();return 0;
}/
// reference: http://thispointer.com/shared_ptr-binary-trees-and-the-problem-of-cyclic-references/
class Node
{int value;
public:std::shared_ptr<Node> leftPtr;std::shared_ptr<Node> rightPtr;// Just Changed the shared_ptr to weak_ptrstd::weak_ptr<Node> parentPtr;Node(int val) : value(val)     {std::cout << "Contructor" << std::endl;}~Node()     {std::cout << "Destructor" << std::endl;}
};int test_weak_ptr5()
{std::shared_ptr<Node> ptr = std::make_shared<Node>(4);ptr->leftPtr = std::make_shared<Node>(2);ptr->leftPtr->parentPtr = ptr;ptr->rightPtr = std::make_shared<Node>(5);ptr->rightPtr->parentPtr = ptr;std::cout << "ptr reference count = " << ptr.use_count() << std::endl;std::cout << "ptr->leftPtr reference count = " << ptr->leftPtr.use_count() << std::endl;std::cout << "ptr->rightPtr reference count = " << ptr->rightPtr.use_count() << std::endl;std::cout << "ptr->rightPtr->parentPtr reference count = " << ptr->rightPtr->parentPtr.lock().use_count() << std::endl;std::cout << "ptr->leftPtr->parentPtr reference count = " << ptr->leftPtr->parentPtr.lock().use_count() << std::endl;return 0;
}

GitHub:https://github.com/fengbingchun/Messy_Test

總結(jié)

以上是生活随笔為你收集整理的C++11中weak_ptr的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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

歡迎分享!

轉(zhuǎn)載請(qǐng)說(shuō)明來(lái)源于"生活随笔",并保留原作者的名字。

本文地址:C++11中weak_ptr的使用