2015-12-20 63 views
0

考慮下面的代碼片段:共享指針初始化列表構造和改變它的類型構造

#include <memory> 
#include <typeinfo> 
#include <iostream> 


class Widget { 
}; 

int main() { 
    auto shared_ptr_to_widget = std::shared_ptr<Widget>({}); 
    std::cout << "type of shared_ptr_to_widget: " << typeid(shared_ptr_to_widget).name() << std::endl; 
    auto maybe_a_widget = *shared_ptr_to_widget; 
    std::cout << "type of maybe_a_widget: " << typeid(maybe_a_widget).name() << std::endl; 
} 

這將輸出:

> type of shared_ptr_to_widget: St10shared_ptrI6WidgetE 
> type of maybe_a_widget: 6Widget 

但是,如果我用替換Widget類:

class Widget { 
public: 
    Widget(): a{1}{} 
    int a; 
}; 

然後它在下列行處發生故障:

auto maybe_a_widget = *shared_ptr_to_widget; 

我明白如果我真的想做一個共享指針指向一個對象的實例,我應該使用

std::make_shared<Widget>() 

,這實際上將調用控件的構造函數,一切都將是罰款和花花公子。但我真的很想了解這裏發生了什麼,以及爲什麼行爲會根據Widget類的構造函數進行更改。

我試過看shared_ptr的構造函數http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr但我有點迷路。我認爲這是我對使用空初始化程序列表作爲參數shared_ptr>()時實際發生的事情缺乏理解。

回答

2

您的代碼具有未定義的行爲,因爲*shared_ptr_to_widget解除引用空指針,因爲您只有默認構造的shared_ptr_to_widget,這會導致一個空的共享指針不擁有任何內容。

在其中執行程序已不確定的行爲來看,C++標準規定沒有約束上一致的實現的行爲,所以任何事情都有可能發生。您正在觀察「任何事物」的特定實例。

要創建一個擁有小部件的指針,或者說

auto shared_ptr_to_widget = std::shared_ptr<Widget>(new Widget); // bad 

auto shared_ptr_to_widget = std::make_shared<Widget>(); // good 
+0

編譯器如何讓過去那個階段中率先實施的Widget?在兩種情況下,它應該是一個指向Widget類的空指針? –

+0

@BrockHargreaves:我不知道,問問你的編譯器(即看看機器代碼)!辯論未定義行爲的細節通常沒有什麼價值。任何事情都可能發生,你看到的任何「任何東西」的味道基本上是不相關的。如果按下,我會說因爲原始的部件是trival和空的,所以不需要生成任何代碼來初始化它(所有類型的值都是相等的),所以缺少一個值就沒有被注意到。 –

+0

是的,如果您也輸出共享指針的使用計數爲零,這並不奇怪。我希望它會在兩種情況下都會出現故障。感謝您的回答。 –