2014-09-18 114 views
69

cplusplus.com shared_ptr page呼籲區分std::shared_ptrshared_ptrcppreference.com page沒有明確地指出區別,但在其std::shared_ptr行爲的描述中同時使用「空」和nullptrC++中的空std :: shared_ptr與空std :: shared_ptr有什麼區別?

空和空之間有區別嗎?有這種混合行爲指針的用例嗎?非空的空shared_ptr甚至有意義嗎?在正常使用情況下(即,如果你沒有明確地構造一個)會不會有一個情況,你最終可能會得到一個空的,但非空的shared_ptr

如果您使用Boost版本而不是C++ 11版本,那麼這些答案中的任何一個都會改變嗎?

回答

72

這是一個奇怪的角落shared_ptr的行爲。它有一個構造函數,可以讓你做一個shared_ptr擁有東西,別的東西:

template< class Y > 
shared_ptr(const shared_ptr<Y>& r, T *ptr); 

shared_ptr使用此構造股份所有權r構造,但什麼ptr指向(即,呼叫get()operator->()將返回ptr)。在ptr指向r擁有的對象的子對象(例如數據成員)的情況下,這很方便。

你鏈接的頁面調用一個shared_ptr擁有什麼shared_ptr指向什麼(即其get() == nullptr。 (在這個意義上由標準使用; null不是。)您可以構造一個空但非空的shared_ptr,但它不會非常有用。一個非空的shared_ptr本質上是一個非擁有指針,它可以用來做一些奇怪的事情,比如passing a pointer to something allocated on the stack to a function expecting a shared_ptr(但是我建議先衝出誰把shared_ptr放在API裏面)。

boost::shared_ptrhas this constructor,他們稱之爲別名構造函數

+7

值得注意的是: ** C++ 11§20.7.2.2.1(p16)**「注意:這個構造函數允許創建一個帶有非NULL存儲指針的空'shared_ptr'實例。」另外值得一提的是前面的註釋(p15),「爲了避免懸掛指針的可能性,這個構造函數的用戶必須確保'p'至少在'r'所有權組被破壞之前保持有效。確實很少使用的結構。 – WhozCraig 2014-09-18 19:31:16

+0

@Cubbi'get()'返回'nullptr' *的'shared_ptr' *不管它是否擁有任何東西,都會與nullptr相比。 – 2014-09-18 20:55:27

+3

一個空但非空的''shared_ptr's *可以很有用,以確保一旦所有擁有的指針超出了作用域(即使在例外的情況下!),一些函數就會被執行。不確定,現在是否有專門的課程。 – coldfix 2014-09-18 20:58:39

2

空的和空的shared_ptr之間有區別嗎?

shared_ptr沒有控制塊,其使用計數被認爲是0.空shared_ptr的副本是另一個空的shared_ptr。它們都是獨立的shared_ptr,它們不共享通用控制塊,因爲它們沒有共享控制塊。空shared_ptr可以使用默認構造函數或使用nullptr的構造函數構造。

非空null shared_ptr有控制塊,可以與其他shared_ptr s共享。非空的空副本shared_ptrshared_ptr,它與原始的shared_ptr共享相同的控制塊,所以使用count不爲0. 可以說shared_ptr的所有副本共享相同的nullptr。非空空shared_ptr可以與對象的類型(未nullptr

這裏的空指針被構造爲例如:

#include <iostream> 
#include <memory> 

int main() 
{ 
    std::cout << "std::shared_ptr<int> ptr1:" << std::endl; 
    { 
     std::shared_ptr<int> ptr1; 
     std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl; 
     std::shared_ptr<int> ptr2 = ptr1; 
     std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl;   
     std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; 
    } 
    std::cout << std::endl; 

    std::cout << "std::shared_ptr<int> ptr1(nullptr):" << std::endl; 
    { 
     std::shared_ptr<int> ptr1(nullptr); 
     std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl; 
     std::shared_ptr<int> ptr2 = ptr1; 
     std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl;   
     std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; 
    } 
    std::cout << std::endl; 

    std::cout << "std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))" << std::endl; 
    { 
     std::shared_ptr<int> ptr1(static_cast<int*>(nullptr)); 
     std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl; 
     std::shared_ptr<int> ptr2 = ptr1; 
     std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl;   
     std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; 
    } 
    std::cout << std::endl; 

    return 0; 
} 

它輸出:

std::shared_ptr<int> ptr1: 
    use count before copying ptr: 0 
    use count after copying ptr: 0 
    ptr1 is null 

std::shared_ptr<int> ptr1(nullptr): 
    use count before copying ptr: 0 
    use count after copying ptr: 0 
    ptr1 is null 

std::shared_ptr<int> ptr1(static_cast<int*>(nullptr)) 
    use count before copying ptr: 1 
    use count after copying ptr: 2 
    ptr1 is null 

http://coliru.stacked-crooked.com/a/54f59730905ed2ff

+0

我認爲這更好回答了爲什麼我們必須檢查shared_ptr的定製刪除程序中的空值。 [在shared_ptr的自定義刪除中檢查nullptr是否合理?](https://stackoverflow.com/questions/42962515/does-it-make-sense-to-check-for-nullptr-in-custom-deleter -of-共享-PTR/42962962) – 2017-07-10 12:47:41

相關問題