2015-10-08 3 views
3

Я с готовностью признаю, что все еще изучаю более тонкие ноты указателей на C/C++ и как они работают, но после некоторых исследований я просто не чувствую, что удобно с кодом ниже.Необработанный указатель внутри std :: make_shared

std::shared_ptr<CDKSCREEN> cdkScreen; 
cdkScreen = std::make_shared<CDKSCREEN>(*initCDKScreen(newWin.get())); 

использование сырья указателей внутри std::shared_ptr свести на нет ли какой-либо из преимуществ, которые вы получаете от использования смарт-указатели? Или это все равно? Спасибо, и я ценю любые ответы на этот пост.


EDIT: Я не в полной мере реализовать цель функции reset(), но спасибо всем, кто указал на это мне. Кажется, я могу передать пользовательский деструктор std::shared_ptr, а также, как показано ниже:

std::shared_ptr<CDKSCREEN> cdkScreen(initCDKScreen(newWin.get()), destroyCDKScreen); 
+0

Я не уверен, что я понимаю вопрос, 'make_shared' строит динамически выделенный объект внутри. Вы можете поставлять необработанный указатель только при прямом создании объекта 'shared_ptr'. – JAB

+0

@JAB вызывает код-ctor в этом случае –

+0

@BartekBanachewicz Это означает, что CDKSCREEN сам по себе является указателем на какой-то тип и, таким образом, делает использование shared_ptr несущественным, поскольку объект, на который указывает, не получит преимуществ от его использования , – JAB

ответ

4

Я считаю, что ваш пример действительно имеет утечку памяти. Давайте разложим его:

CDKSCREEN* screen = initCDKScreen(newWin.get()); 
CDKSCREEN& screenRef = *screen; 

// auto screenSharedPtr = std::make_shared<CDKSCREEN>(screenRef); 
// this is basically: 

CDKSCREEN* screen2 = new CDKSCREEN(screenRef); 
shared_ptr<CDKSCREEN> screenSharedPtr (screen2); 

Как вы можете видеть, копия выполняется, но исходный указатель не удаляется. К сожалению.


Если initCDKScreen возвращает то, что должно быть просто delete d, то в этом случае я бы избежать копирования/перемещения CTOR и просто .reset() смарт-указатель на него:

std::shared_ptr<CDKSCREEN> cdkScreen; 
cdkScreen.reset(initCDKScreen(newWin.get())); 

На самом деле, так как он имеет даже перегрузки конструктора для этого, идти вперед и

std::shared_ptr<CDKSCREEN> cdkScreen { initCDKScreen(newWin.get()) }; 

Если объект пользовательского разрушения требуется, вы можете передать его в качестве 2-го параметр указателю. Это имеет прекрасный смысл, и для этого были разработаны умные классы указателей.

+0

Ooops, я думаю, это была довольно грубая ошибка :) Спасибо за такой потрясающий ответ, я также не понимал, что вы можете передать собственный деструктор как второй параметр, как описано ниже JojOatXGME ниже. Я не видел этого ни в одном из примеров, на которые я смотрел. –

1

ли использование сырья указателей внутри станда :: shared_ptr аннулирует любого из преимуществ, которые вы получаете от использования смарта-указателей? Или это все равно? Спасибо, и я ценю любые ответы на этот пост.

Нет, это целая цель умного указателя. Вы больше не отвечаете за обслуживание необработанного указателя. Объект интеллектуального указателя. Объект интеллектуального указателя берет на себя роль необработанного указателя. Когда интеллектуальный указатель истекает (выходит из области видимости или удаляется), он автоматически удаляет указатель, которому он владеет. Важным здесь является область действия: таким образом вам не нужно забывать удалять его самостоятельно, если вы return или throw где-то.

unique_ptr пытается описать концепцию, что существует только один текущий поток выполнения, который использует объект. shared_ptr раскрывает это, заявляя, что там может быть несколькими потоками, пытающимися получить к нему доступ одновременно. Но помните: shared_ptr НЕ гарантирует параллелизм или безопасность для объекта, на который он указывает. Это гарантирует только параллельность и безопасность самого указателя.

5

Я думаю, вы хотите сохранить указатель, возвращенный initCDKScreen. В этом случае вам не нужно использовать make_shared.Вы должны передать указатель на конструктор или shared_ptr::reset(...):

std::shared_ptr<CDKSCREEN> cdkScreen(initCDKScreen(newWin.get())); 

С CDKSCREEN должен быть разрушен destroyCDKScreen(CDKSCREEN *screen), а не с delete, вы должны написать что-то вроде этого:

std::shared_ptr<CDKSCREEN> cdkScreen(initCDKScreen(newWin.get()), destroyCDKScreen); 

или

std::shared_ptr<CDKSCREEN> cdkScreen; 
cdkScreen.reset(initCDKScreen(newWin.get()), destroyCDKScreen); 
+0

Да, я хотел бы сохранить возвращаемый указатель и использовать его во всем приложении в качестве основного источника создания экранов. Извините, я так не объяснил это. Я также не понимал, что вы можете передать ему индивидуальный деструктор, поскольку это не было показано ни в одном из примеров, на которые я смотрел. Я тоже не понял цели цели, и до сих пор. Спасибо за замечательный ответ :) –

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

  • Нет связанных вопросов^_^