2013-08-21 3 views
0

Может ли кто-нибудь сказать мне разницу между этими двумя методами при использовании, как показано ниже?В чем разница между возвратом boost :: shared_ptr и построением boost :: shared_ptr из возвращаемого исходного указателя?

Если я использую CreateBoostContainer, мой код работает хорошо. Однако, если я использую CreateContainer, я получаю исключение boost :: bad_weak_ptr позже в коде в функции Foo при попытке использовать shared_from_this в ContainerC. Я использую только один поток.

Спасибо!

Использование:

SceneElementNodeC* poNode(new SceneElementNodeC(CreateBoostContainer())); 
SceneElementNodeC* poNode(new SceneElementNodeC(boost::shared_ptr<SceneElementI>(CreateContainer()))); 

Определения:

boost::shared_ptr<SceneElementI> LoaderC::CreateBoostContainer() const 
{ 
    return boost::shared_ptr<SceneElementI>(new ContainerC()); 
} 

SceneElementI* LoaderC::CreateContainer() const 
{ 
    return new ContainerC(); 
} 

SceneElementNodeC:

class SceneElementNodeC 
{ 
    SceneElementNodeC(boost::shared_ptr<SceneElementI> spSceneElement) 
    : m_spSceneElement(spSceneElement) 
    {}; 
} 

ContainerC:

class ContainerC : public SceneElementI, public boost::enable_shared_from_this<ContainerC> 
{ 
    ContainerC() 
    {}; 

    void Foo(VisitorI* poVisitor) 
    { 
     poVisitor->Visit(shared_from_this()); 
    }; 
} 

ответ

1

Во-первых, CreateBoostContainer это имя страшная, библиотека подталкивания содержит сотни компонентов, в том числе несколько контейнеров, shared_ptr только одна небольшая часть Boost. Если вы позже изменили код, чтобы вернуть std::shared_ptr, вместо этого вам придется переименовать функции, так что бы вы изменили его на CreateStdContainer?!

Во-вторых, вам не удалось предоставить полный код, который позволяет воспроизводить проблему, поэтому в соответствии с правилами Stackoverflow ваш вопрос должен быть закрыт!Я предполагаю, что ваш тип определяется следующим образом:

class ContainerC 
: public SceneElementI, public boost::enable_shared_from_this<ContainerC> 
{ 
    // ... 
}; 

Разница заключается в том, что в этой функции:

boost::shared_ptr<SceneElementI> LoaderC::CreateBoostContainer() const 
{ 
    return boost::shared_ptr<SceneElementI>(new ContainerC()); 
} 

инициализации shared_ptr с ContainerC* так в shared_ptr конструктор может обнаружить, что является базовым классом enable_shared_from_this (неявным enable_shared_from_this<ContainerC> к вентиляционным шахтам)

в то время как в этой функции:

SceneElementI* LoaderC::CreateContainer() const 
{ 
    return new ContainerC(); 
} 

вы теряете информацию об динамическом типе объекта путем преобразования указателя в базовый класс перед созданием shared_ptr. Возвращаемый указатель равен SceneElementI*, который (я предполагаю) не имеет базового класса enable_shared_from_this, поэтому, когда этот указатель позже используется для инициализации shared_ptr, невозможно сказать, что он указывает на базовый класс типа, который также получен из enable_shared_from_this<ContainerC>.

Вы можете сделать первую функцию также не работает, делая это:

boost::shared_ptr<SceneElementI> LoaderC::CreateBoostContainer() const 
{ 
    SceneElementI* ptr = new ContainerC(); 
    return boost::shared_ptr<SceneElementI>(ptr); 
} 

Это эквивалентно, так как он преобразует указатель SceneElement* перед созданием shared_ptr.

shared_ptr умна и использует тип указателя вы строите его, даже если это не тип хранится в shared_ptr, поэтому если вы вентиляционный, что указатель первого затем shared_ptr не может быть умным.

+0

Прежде всего, спасибо за проработку разницы, именно этого я и не понял. – schluchc

+0

Что касается именования CreateBoostContainer, то, конечно, это ужасно, но это было просто отличить две функции в этом вопросе. Что касается второго момента, вы правы, но я надеюсь, что в таком случае у вас все еще есть шанс улучшить вопрос (который я обязательно сделаю) вместо того, чтобы сразу закрыть его;) – schluchc

1

Documentation for enable_shared_from_this

Требуется: enable_shared_from_this должен быть доступен базовый класс Т. * это должно быть подобъектом экземпляра т типа Т. Там должен существовать как минимум один экземпляр shared_ptr p, которому принадлежит t.

Обратите внимание, «Там должно существовать по крайней мере один shared_ptr экземпляр р, которому принадлежит т».

Если вы используете CreateContainer, тогда нет shared_ptr экземпляра, которому это принадлежит.

+0

Созданный объект SceneElementNodeC владеет shared_pointer, так что есть один, или я ошибаюсь? – schluchc

1

Using the raw pointer at all is poor form. Вот почему типично использовать что-то вроде std::make_shared - для предотвращения возможной утечки памяти. Считайте, что исключение может быть выбрано между точкой, в которой вы начинаете свой класс, и когда он связан с интеллектуальным указателем.

Сказав это, я считаю, что это всего лишь деталь реализации того, как работает enable_shared_from_this.

+0

Даже если это деталь реализации, в чем разница, пользуюсь ли я первым или вторым методом? Я не вижу никакой разницы в тот момент, когда используется shared_from_this, то есть когда построенный SceneElementNodeC владеет shared_pointer. – schluchc

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