Reputation: 1219
I have the following setup:
class Foo {
public:
Foo() {}
vector<BigObject*> mPointers;
};
class Bar {
public:
Foo *exposeSomeFoo() { return &mFoos[42]; }
private:
vector<Foo> mFoos;
vector<BigObject> mMemoryManaged;
};
I'm basically trying to make sure that at no point in my code will someone accidentally use a Foo
for which the Bar
it was exposed from has gone out of scope.
But this is obviously problematic. If I expose pointers to Foo
like above, they become invalid once Bar
goes out of scope. If I instead use Foo exposeSomeFoo()
, the mPointers
will become invalid once Bar
goes out of scope, too - and returning copies seems like a bad idea if mPointers
has a lot of elements!
I've tried solving this by making a private copy constructor:
class Foo {
public:
Foo() {}
vector<BigObject*> mPointers;
private:
Foo(const Foo&);
};
But then I get errors when I try to insert a Foo
into mFoos
from within Bar
.
There must be a paradigm that allows full memory safety while still allowing me to expose functionality like this. How can I expose, to code elsewhere, a composite object from Bar
whose memory is managed specifically by Bar
or at least in the compilation unit itself?
Upvotes: 0
Views: 71
Reputation: 1219
Actually, I ended up doing something like this:
class Foo {
public:
Foo(shared_ptr<vector<BigObject> > bigObjects) : mBigObjects(bigObjects) {
}
private:
vector<BigObject*> mPointers;
shared_ptr<vector<BigObject> > mBigObjects;
};
class Bar {
public:
Bar() {
mBigObjects = shared_ptr<vector<BigObject> >(new vector<BigObject>);
for (int i = 0; i < 100; i++)
mBigObjects->push_back(BigObject());
for (int i = 0; i < 100; i++)
mFoos.push_back(Foo(mBigObjects));
}
Foo exposeSomeFoo() { return mFoos[42]; }
private:
shared_ptr<vector<BigObject> > mBigObjects;
vector<Foo> mFoos;
};
I think this is the behavior I want: only when all instances of both Foo
and Bar
are destroyed, is the vector with BigObjects actually destroyed. Can someone double-check that this is safe and good practice? Thanks!
Upvotes: 0
Reputation: 303087
If you want to make sure that all of your objects can share resources, such that the resource is alive as long as all of the objects are, just use std::shared_ptr
everywhere:
class Foo {
public:
Foo() {}
vector<shared_ptr<BigObject>> mPointers;
};
class Bar {
public:
shared_ptr<Foo> exposeSomeFoo() { return mFoos[42]; }
private:
vector<shared_ptr<Foo>> mFoos;
vector<shared_ptr<BigObject>> mMemoryManaged;
};
That way, a caller can hold onto bar.exposeSomeFoo()
without worry - the caller now shares ownsership of it, sot his will be perfectly safe.
Upvotes: 1