2015-12-20 2 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: Я не знаю, спросите своего компилятора (например, посмотрите на машинный код)! В общем, очень мало смысла обсуждать детали неопределенного поведения. Все может случиться, и какой вкус «ничего», который вы видите, в основном не имеет значения. Если нажать, я бы сказал, что, поскольку исходный виджет треугольный и пустой, для его инициализации не нужно генерировать код (все значения этого типа равны), и поэтому отсутствие значения оставалось незамеченным. –

+0

Да, неудивительно, что если вы также выведите количество использования общего указателя, оно равно нулю. Однако я хотел бы, чтобы это произошло в обоих сценариях. Спасибо за Ваш ответ. –

Смежные вопросы