2015-09-07 3 views
1

рассмотрим следующий кодповторного назначения shared_ptr внутри указываемого объекта

struct base { 
    virtual void bar(std::shared_ptr<base>&) = 0; 
}; 

struct foo1 : base { /* ... */ }; 

struct foo2 : base { 
    void bar(std::shared_ptr<base>&obj) 
    { 
    // ... 
    if(some_condition) 
     obj = std::make_shared<foo1>(); // re-assign obj 
    // ... 
    } 
}; 

std::shared_ptr<base> x = std::make_shared<foo2>(); 
x->bar(x);        // last line 

envoke ли этот код UB? (примечание: повторная присвоение obj уничтожит объект вызова объекта вызова foo2::bar при вызове из последней строки). Если после этого не будут получены данные из bar, будет ли код все еще в порядке?

Альтернативный способ кодирования это будет

struct base { 
    virtual std::shared_ptr<base> bar(std::shared_ptr<base>) = 0; 
}; 
struct foo1 : base { /* ... */ }; 

struct foo2 : base { 
    std::shared_ptr<base> bar(std::shared_ptr<base> obj) 
    { 
    // ... 
    if(some_condition) 
     obj = std::make_shared<foo1>(); 
    // ... 
    return obj; 
    } 
}; 

std::shared_ptr<base> x = std::make_shared<foo2>(); 
x=x->bar(x); 

, которые должны быть безопасными в любом случае, не так ли? Является ли дополнительное копирование в этом кодере проблемой производительности?


редактировать. После того, как Крис ответа, я имел взгляд на shared_from_this, что позволяет альтернативная реализация

struct base : std::enable_shared_from_this<base> { 
    virtual std::shared_ptr<base> bar() = 0; 
}; 
struct foo1 : base { /* ... */ }; 

struct foo2 : base { 
    std::shared_ptr<base> bar() 
    { 
    auto obj = shared_from_this(); 
    if(some_condition) 
     obj = std::make_shared<foo1>(); 
    // ... 
    return obj; 
    } 
}; 

std::shared_ptr<base> x = std::make_shared<foo2>(); 
x=x->bar(); 

ответ

1

Как это ссылка указывает, что это безопасно и не UB к delete this в методе, даже если это немного сбивает с толку.

Is it safe to `delete this`?

Я не думаю, что дополнительное копирование является проблемой. Чтобы быть уверенным, что вам придется профилировать. Отсутствие профилирующей информации, если бы это был я, я бы предпочел второй подход к первому b/c, для программиста это проще понять, но это в значительной степени мнение.

Возможно, вы также захотите заглянуть в шаблон shared_from_this в C++ 11, если вы хотите упростить объекты для управления общими указателями для себя и так далее.

+0

благодарит за напоминание о 'shared_from_this'. – Walter

+0

Пожалуйста, посмотрите мой отредактированный вопрос, то есть код с использованием 'shared_from_this' - вот как это следует использовать? – Walter

+0

уверен, я думаю, что даже более просто это может быть 'if (some_condition) {return std :: make_shared (); } else {return shared_from_this(); } ' –