【问题标题】:Shared pointer initializer list constructor and changes to it's type constructor共享指针初始化器列表构造函数及其类型构造函数的更改
【发布时间】:2015-12-20 23:40:51
【问题描述】:

考虑以下 sn-p:

#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 的构造函数,一切都会很好。但我真的很想了解这里发生了什么以及为什么行为会根据 Widget 类的构造函数而改变。

我已经尝试查看 shared_ptr http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr 的构造函数,但我有点迷失了。我想这是我对使用空初始值设定项列表作为 shared_ptr() 的参数时实际发生的情况缺乏了解。

【问题讨论】:

    标签: c++


    【解决方案1】:

    您的代码具有未定义的行为,因为 *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
    

    【讨论】:

    • 在 Widget 的第一个实现中,编译器是如何通过那个阶段的?在这两种情况下,它都应该是一个指向 Widget 类型的类的空指针?
    • @BrockHargreaves:我不知道,请询问您的编译器(即查看机器代码)!辩论未定义行为的细节通常没有什么价值。任何事情都有可能发生,你所看到的“任何事情”的味道基本上是无关紧要的。如果按下,我会说因为原始小部件是琐碎和空的,不需要生成代码来初始化它(类型的所有值都是相等的),因此没有注意到值的缺失。
    • 是的,如果您还输出共享指针的使用计数,它为零也就不足为奇了。我希望它在这两种情况下都会出现故障。谢谢你的回答。
    猜你喜欢
    • 2015-10-09
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 2013-10-03
    • 2015-11-05
    • 2013-11-17
    相关资源
    最近更新 更多