2015-06-09 11 views
2

Если я делаю следующее,Удалить сырой указатель после создания shared_ptr из него

int* p = new int(10); 
std::shared_ptr<int>(p); 
delete p; 

Что здесь происходит? Недействителен ли shared_ptr после удаления исходного указателя? Есть ли способ обеспечить безопасность доступа к памяти в таком сценарии?

+0

Могу ли я спросить, зачем вам это нужно? Я имею в виду, почему бы не использовать 'shared_ptr' в первую очередь – Bill

+0

У меня есть функция, которая принимает параметр shared_ptr как параметр. Я просто пытаюсь найти случаи, когда моя функция будет ошибочной, если клиент API выполняет такие глупые вещи, как описано выше, и посмотреть, есть ли что-нибудь, что я могу сделать в своей функции, чтобы это не произошло. Есть предположения? – SkypeMeSM

+4

Нет, если ваш клиент решает стрелять себе в ногу, вы не можете многое сделать с этим. – Praetorian

ответ

6

Код в вашем вопросе содержит 2 противоречивых определения p. Я предполагаю, что вы имели в виду, чтобы получить возможность отправлять что-то вроде

int* p = new int(10); 
std::shared_ptr<int> p1(p); 
delete p; 

Когда shared_ptr выходит из области видимости и счетчик ссылок падает до нуля, он будет пытаться delete p;, что приводит к двойному удалению и непредсказуемое поведение.

Вы перешли в собственность динамически выделяется int к shared_ptr, так что пусть это делают свою работу, а не идти об удалении int самостоятельно.


Если вы хотите клиентов вашего API от делать что-то похожее на приведенном выше коде, одна возможность заключается в том, чтобы изменить тип параметра функции API, от shared_ptr к параметру пачке аргументов конструктора. Например

template<typename T, typename... Args> 
void api_func(Args&&... args) 
{ 
    auto p = std::make_shared<T>(std::forward<Args>(args)...); 
    // Use the shared_ptr p as before 
} 

Затем, вместо того, чтобы передать shared_ptr<int>, клиентский код будет вызывать выше функцию api_func<int>(10);.

+0

'std :: shared_ptr (p);' создает временное значение. Это не декларация 'p'. В момент вызова 'delete p;' память уже была освобождена деструктором 'shared_ptr'. – tsuki

+0

@tsuki Нет, круглые скобки там избыточны, поэтому это объявление 'shared_ptr ' named 'p' (в этом случае это исправление' p', следовательно, ошибка). – Praetorian

+0

Да, это интересно. Извините, я пытался быть умным, не запуская код. – tsuki