你能设置一个weak_ptr<>在演员?

时间:2011-09-21 16:44:06

标签: c++ reference

以下代码无法在Visual C ++ 11中使用此错误进行编译:

  

1> c:\ users \ tony \ documents \ visual studio 11 \ projects \ cpp11_ex1 \ cpp11_ex1 \ main.cpp(52):错误C2440:'':无法从'Foo * const'转换为'std ::的weak_ptr< _Ty>'

#include <stdio.h>
#include <memory>

using namespace std;

class Foo;

class Bar
{
public:
    Bar( weak_ptr<Foo> foo ) : _foo(foo) { printf("Bar(%p)\n",this); }
    ~Bar() { printf("~Bar(%p)\n",this); }
private:
    weak_ptr<Foo> _foo;
};

class Foo
{
public:
    Foo() : _bar() { _bar = make_shared<Bar>( weak_ptr<Foo>(this) );  printf("Foo(%p)\n",this); }
    ~Foo() { printf("~Foo(%p)\n",this); }
private:
    shared_ptr<Bar> _bar;
};

int main( int argc, char* argv[] )
{
    shared_ptr<Foo> instance = make_shared<Foo>();

    return 0;
}

似乎我无法从原始weak_ptr指针创建this。这引起了一系列有趣的问题。

  1. 由于我在Foo的ctor中尝试此操作,Foo的引用计数为0(即main中的make_shared<>尚未返回)。< / p>

  2. 我发现我可以从 weak_ptr创建shared_ptr s ...但是如果我改变Bar ctor采取shared_ptr,我调用Bar的构造函数的行为最终会破坏Foo! (由于Foo的引用计数仍为0,因此通过调用shared_ptr的ctor创建(然后销毁)FooBar

  3. 我真正想做的就是创建Foo,创建Foo拥有一个Bar,但让Bar变弱引用回Foo。我真的不想被迫进入2部分初始化!

3 个答案:

答案 0 :(得分:2)

boost::weak_ptr<T>用于存储,而不是用于。

您希望传递boost::shared_ptr个对象,然后将它们存储在boost::weak_ptr个对象(通常是私有的)中。

struct Foo {

  Foo(const boost::shared_ptr<int> &data) : weak_data(data) {}

  boost::shared_ptr<int> getData() {
    boost::shared_ptr<int> data = weak_data.lock();
    if (!data)
      throw std::runtime_error("data is no longer valid");
    return data;
  }

private:
  boost::weak_ptr<int> weak_data;

};

无论你是扔还是回传,空shared_ptr<T>取决于你。如果你不能锁定对象,你不应该再传递它。那时它真的无效。

话虽如此,您可能希望避免以这种方式创建共享指针。您的示例中不清楚您是否需要此设计。如果你可以像Mooing Duck这样的方式重新设计它,那么你会更加诚实。

从类似的经验来看,当我需要像这样的循环依赖时,它可能不是一个简单的构造场景。我会看一个两部分构造函数(静态命名构造函数,或者也许是构建器)来管理创建两个对象并确保它们的引用是有效的。

以下是一个简单命名构造函数的快速示例。

class Foo;

// Likely that this should be a child class of Foo
class Bar {
private:
  friend class Foo;
  Bar(const boost::shared_ptr<Foo> &foo) : weak_foo(foo) {}
  weak_ptr<Foo> weak_foo;
};

class Foo {
public:
  static boost::shared_ptr<Foo> CreateFoo() {
    boost::shared_ptr<Foo> foo = boost::shared_ptr<Foo>(new Foo);
    foo.bar = boost::make_shared<Bar>(foo);
    return foo;
  }

private:
  Foo() {}
  boost::shared_ptr<Bar> bar;
};

在这里,您可以控制正确创建foobar变量的不变量。

答案 1 :(得分:0)

根据定义,在没有指向同一对象的强指针的情况下,不可能有一个弱指针。当最后一个强指针消失时,所有弱指针都变为空。这就是所有弱点。

编写自己的函数,将共享ptr返回给Foo(Foo工厂),并从该指针初始化Bar中的弱ptr。

答案 2 :(得分:0)

由于shared_ptr将指向Foo,并且Bar将始终由Bar的shared_pointer拥有,因此如果Bar存在,则Foo存在。因此,你不需要Bar中的智能指针。 (如果我理解正确的问题)

#include <stdio.h>
#include <memory>

using namespace std;

class Foo;

class Bar
{
public:
    Bar( Foo* foo ) : _foo(foo) { printf("Bar(%p)\n",this); }
    ~Bar() { printf("~Bar(%p)\n",this); }
private:
    Foo* _foo;
};

class Foo
{
public:
    Foo() : _bar(new Bar(this)) { printf("Foo(%p)\n",this); }
    ~Foo() { printf("~Foo(%p)\n",this); }
private:
    shared_ptr<Bar> _bar;
};

int main( int argc, char* argv[] )
{
    shared_ptr<Foo> instance = make_shared<Foo>();
    return 0;
}