Brock Hargreaves
Brock Hargreaves

Reputation: 872

Shared pointer initializer list constructor and changes to it's type constructor

Consider the following snippet:

#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;
}

This will output:

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

However, if I replace the Widget class with:

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

Then it seg faults at the following line:

auto maybe_a_widget = *shared_ptr_to_widget;

I understand if I actually wanted to make a shared pointer to an instance of an object I should use

std::make_shared<Widget>()

and this would actually call the constructor of Widget and everything would be fine and dandy. But I'd really like to understand what is going on here and why the behaviour changes based on the constructor of the Widget class.

I've tried looking at the constructors for shared_ptr http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr but I get a bit lost. I imagine it's my lack of understanding in what is actually happening when using an empty initializer list as a parameter to shared_ptr<>().

Upvotes: 0

Views: 98

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 477000

Your code has undefined behaviour, since *shared_ptr_to_widget dereferences a null pointer, since you only default-constructed shared_ptr_to_widget, which results in an empty shared pointer that doesn't own anything.

At the point where the program execution has undefined behaviour, the C++ standard imposes no constraints on the behaviour of a conforming implementation, so anything can happen. You are observing a particular instance of "anything".

To create a pointer that owns a widget, say either

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

or

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

Upvotes: 2

Related Questions