網(wǎng)站上傳照片失敗東莞seo外包公司哪家好
shared_ptr
shared_ptr繼承自__shared_ptr,其中有兩個對象,一個是指向資源的指針,一個是控制塊,指向一個引用計數(shù)對象??刂茐K中存儲了強(qiáng)引用和弱引用的計數(shù),強(qiáng)引用Uses代表shared_ptr對象的引用計數(shù),弱引用Weaks代表weak_ptr對象的引用計數(shù)。
大概結(jié)構(gòu)如上圖所示,控制塊其中也存儲了指向資源的指針。
因此在構(gòu)造一個shared_ptr對象的時候,會有兩次堆分配,一次是為資源分配,一次是為控制塊分配。因為每一個指向這份資源的指針對象都需要看到同一份引用計數(shù),因此跟資源一樣也是堆分配的。多次的堆分配和釋放也就代表效率上的損失,而且極易產(chǎn)生內(nèi)存碎片。
make_shared
C++11同時提供了make_shared函數(shù),這是通過構(gòu)造一個shared_ptr對象,而這個對象會事先申請一塊足夠大的內(nèi)存空間,用于存放管理的資源以及控制塊。即分配的堆空間是連續(xù)的,因此只有一次堆內(nèi)存分配。
內(nèi)存的結(jié)構(gòu)就從左邊的構(gòu)造shared_ptr對象到右邊的重構(gòu)對象資源指針和引用計數(shù)。
相比shared_ptr構(gòu)造,減少一次內(nèi)存分配,提高效率,并且內(nèi)存空間連續(xù),減少內(nèi)存碎片產(chǎn)生。但是,make_shared也存在缺點(diǎn)。
make_shared的缺點(diǎn)
自定義deleter
make_shared在構(gòu)造智能指針對象的時候不能自定義deleter。在創(chuàng)建對象時同時創(chuàng)建控制塊,這個控制塊內(nèi)部包含了引用計數(shù)、deleter等與管理資源相關(guān)的信息。因為資源和控制塊是屬于同一塊申請的內(nèi)存,所以使用自定義deleter可能會導(dǎo)致控制塊內(nèi)存被不正確地釋放。因此,如果要使用deleter,應(yīng)該使用shared_ptr直接構(gòu)造。
構(gòu)造函數(shù)
因為make_shared需要用到類的拷貝構(gòu)造,因此需要被管理的類的構(gòu)造函數(shù)是public的。
內(nèi)存延遲歸還
因為分配的空間是連續(xù)的,在資源指針的Uses變?yōu)?之后,控制塊伴隨資源的資源不會被立即釋放,要等Weak也變?yōu)?,整塊內(nèi)存才被釋放。資源只是被clear,但是但是沒有歸還操作系統(tǒng)。而如果是默認(rèn)的控制塊,在資源指針的Uses變?yōu)?之后,資源會被立即釋放,內(nèi)存立即歸還。
通過調(diào)試看直接構(gòu)造和make_shared的區(qū)別
void test2()
{std::shared_ptr<string> p1 = std::make_shared<std::string>(10, '9');{std::weak_ptr<std::string> wptr1;wptr1 = p1;std::shared_ptr<string> p2 = std::make_shared<std::string>("Hello");wptr1 = p2;p2 = p1;}std::cout << "end";
}void test1()
{std::shared_ptr<string> p1 = std::shared_ptr<std::string>(new std::string(10, '9'));{std::weak_ptr<std::string> wptr1;wptr1 = p1;std::shared_ptr<string> p2 = std::shared_ptr<std::string>(new std::string("Hello"));wptr1 = p2;p2 = p1;}std::cout << "end";
}int main()
{test1();test2();return 0;
}
直接構(gòu)造
當(dāng)wptr指向p1的時候,可以看到p1的Weaks變?yōu)榱?,weak_ptr觀察到的內(nèi)容與p1一致。并且注意此時control block的value顯示為default,表示默認(rèn)的控制塊。
當(dāng)weak_ptr指向p2,并且將p2指向p1,意思就是p2原來管理的Hello資源要釋放掉,然后用p1拷貝構(gòu)造一個對象,賦值給p2,讓p1和p2同時管理10個9。
此時可以看到weak_ptr的資源指針已經(jīng)顯示Error reading,說明資源已經(jīng)釋放,內(nèi)存已經(jīng)歸還了。
make_shared構(gòu)造
此時可以看到原來為default的control block已經(jīng)改為了make_shared。
重復(fù)之前的操作,把p2指向p1,再看weak_ptr的成員??梢钥吹絧tr指向的資源并沒有被釋放,只是內(nèi)容并清空而已。只有當(dāng)weak_ptr的生命周期結(jié)束,整個內(nèi)存塊才會被釋放,歸還給操作系統(tǒng)。
這就是make_shared最主要的缺點(diǎn),在某些內(nèi)存要求高的場景下可能不太適用。