2015-12-20 101 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

是的,如果您也输出共享指针的使用计数为零,这并不奇怪。我希望它会在两种情况下都会出现故障。感谢您的回答。 –