2013-03-20 2 views
2

Мне нужно обернуть необработанный указатель в shared_ptr, чтобы передать его функции. Функция не будет ссылаться на входной объект после его возвращения.Как обернуть необработанный указатель в shared_ptr и запретить shared_ptr удалять объект?

{ 
    MyClass i; 
    shared_ptr<MyClass> p(&i); 
    f(p); 
    // BAD: shared_ptr will delete i. 
} 

Как предотвратить shared_ptr удалять ссылочный объект?

+2

Вы могли бы дать ему пустой пролет. – chris

+1

ПОЧЕМУ вы хотели бы это сделать? i уже находится в стеке, поэтому нет смысла использовать интеллектуальный указатель - на самом деле, как вы видите, умный указатель закручивает его. Если вам нужно передать указатель на него где-нибудь, используйте raw pointer from & i –

+0

@chris. Это должно работать. Я, вероятно, займусь этим решением. Благодаря! – woodings

ответ

4

Как chris упоминалось в комментарии, написать пустой Deleter:

#include <type_traits> 

template <typename T> 
struct empty_delete 
{ 
    empty_delete() /* noexcept */ 
    { 
    } 

    template <typename U> 
    empty_delete(const empty_delete<U>&, 
     typename std::enable_if< 
      std::is_convertible<U*, T*>::value 
     >::type* = nullptr) /* noexcept */ 
    { 
    } 

    void operator()(T* const) const /* noexcept */ 
    { 
     // do nothing 
    } 
}; 

Пример использования:

#include <iostream> 
#include <memory> 

struct noisy 
{ 
    noisy() { std::cout << "alive" << std::endl; } 
    ~noisy() { std::cout << "dead" << std::endl; } 

    noisy(const noisy&); 
    noisy& operator=(const noisy&); 
}; 

template <typename T> 
void take(T& yours) 
{ 
    std::cout << "Taking..." << std::endl; 
    { 
     auto mine = std::move(yours); 
    } 
    std::cout << "Took." << std::endl; 
} 

int main() 
{ 
    std::unique_ptr<noisy> a(new noisy()); 
    std::shared_ptr<noisy> b(new noisy()); 
    std::unique_ptr<noisy, empty_delete<noisy>> c(new noisy()); 
    std::shared_ptr<noisy> d(new noisy(), empty_delete<noisy>()); 

    take(a); 
    take(b); 
    take(c); 
    take(d); 
} 

Выход:

живых
живых
живой
alive
... ...
Взятие ...
dead
Took.
Принимая ...
Принимал.
Принимая ...
Принимал.

Конечно, этот пример утечки памяти.

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