The following code fails to compile in Visual C++ 11 with this error:
1>c:\users\tony\documents\visual studio 11\projects\cpp11_ex1\cpp11_ex1\main.cpp(52): error C2440: '' : cannot convert from 'Foo *const ' to '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;
}
It seems that I can't create a weak_ptr
from a raw this
pointer. This causes an interesting series of problems.
Since I am attempting this in
Foo
's ctor,Foo
's reference count is 0 (i.e. themake_shared<>
in main hasn't retu开发者_Python百科rned yet).I've discovered that I can create
weak_ptr
s fromshared_ptr
s... But if I changeBar
ctor to take ashared_ptr
, I the act of callingBar
's constructor ends up destroyingFoo
! (SinceFoo
's reference count is still 0, creating (and then destroying) ashared_ptr
toFoo
via a call toBar
's ctor ).
All I really want to do is create Foo
, have Foo
create and own a Bar
, but have Bar
have a weak reference back to Foo
. I really don't want to be forced into 2 part initialization here!
boost::weak_ptr<T>
is for storing, not for using.
You want to pass boost::shared_ptr
objects, and then store them in the boost::weak_ptr
objects (usually private).
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;
};
Whether you throw or pass back and empty shared_ptr<T>
is up to you. If you cannot lock the object though, you shouldn't be passing it around anymore. It really isn't valid at that point.
That being said, you may want to refrain from creating a shared pointer in that manner. It isn't clear from your example if you need this design. If you can redesign it in a way like Mooing Duck suggested you will be better off, in all honesty.
From similar experiences when I needed circular dependencies like this, it probably is not a simple construction scenario. I would look at a two part constructor (static named constructor, or builder perhaps) to manage creating the two objects and ensuring that their references are valid.
Here is a quick example of a simple named constructor.
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;
};
Here you control the invariant that your foo
and bar
variables are created correctly.
Since Foo
will be pointed at by a shared_ptr, and Bar will always be owned by a shared_pointer of Bar, then if Bar exists, Foo exists. Ergo, you don't need a smart pointer in Bar. (If I understand the problem correctly)
#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;
}
It is not possible to have a weak pointer in the absence of strong pointers to the same object, by definition. When the last strong pointer goes away, all the weak pointers turn null. That's all the weak pointers do.
Write your own function that returns a shared ptr to Foo (a Foo factory), and initialize the weak ptr in Bar from that pointer.
精彩评论