2

Consider the following code:

class Child {
   vector<Object>::iterator it;
}

class Parent {
   vector<Object> objects;

   Child getChild(int idx) {
       Child ret;
       ret.it = objects.begin() + idx;
       return ret;
   }
}

Obviously the child must not outlive its parent, but I expect it to be reasonable to try to call something like Child childThing = getParent().getChild(5). How can I prevent this? Is there a pattern to enforce keeping an instance of Parent around? If possible I don't want to copy objects as its contents are quite complex.

Managarm
  • 1,070
  • 3
  • 12
  • 25
  • 2
    You don't want to copy object, but you copy Child `ret`... – Jarod42 Sep 13 '16 at 11:40
  • What is the context of this code? `Child::it` looks like a promise of dangling iterator – rocambille Sep 13 '16 at 11:44
  • @Jarod42 `objects` is the vector in `Parent`. Copying `Child` is ok, I just don't want to copy the vector into the returned child :) – Managarm Sep 13 '16 at 12:00
  • @wasthishelpful `Parent` is guaranteed not to be altered after creation. Thanks for your input though, I'll be mindful of that! – Managarm Sep 13 '16 at 12:01

1 Answers1

1

Having a child as a member of a parent would help you ensure that (specially if you don't hand out references to the child around and save them somewhere else). The principle is simple: the child is constructed inside the parent and it won't be destroyed until the parent is.

As for copying objects, you can always hand out references or pointers. There's no sizable copy penalty there.

In other order of things, iterators (as the one your child has) can easily be invalidated once the contents of their container changes, so I'd be wary of those.

Edit: After your comment, you could try to use a shared_ptr to refer to your parent objects. These will keep the parent alive while at least there's a child with them. std::shared_ptr are reference-counted and have a small overhead over a regular, unmanaged pointer. You could, for example, make a instance of your parent as a std::shared_ptr and then copy this pointer around on the children. Once all children and the parent themselves are out of scope, the parent will be deleted.

The Marlboro Man
  • 971
  • 7
  • 22
  • Child is basically a view on Parent, I can't predict which views will be required and I also don't want them to be kept in Parent for they might not be needed for long :/ – Managarm Sep 13 '16 at 11:41
  • Edited: maybe you could find std::shared_ptr of use. Bind a managed pointer of the parent with your children and let the language do the cleaning for you. – The Marlboro Man Sep 13 '16 at 11:45
  • Hmm, that seems like an option, but I'd have to create parent as a shared_ptr as well. I'll wait a bit to see if there are other suggestions, but if nothing comes up I'll accept your answer :) – Managarm Sep 13 '16 at 11:59
  • That's correct... Working with any kind of pointers may be seen as a nuisance but in this case it could be one (of many, I guess) ways of enforcing your design constraint :). – The Marlboro Man Sep 13 '16 at 12:02
  • I went ahead and implemented your suggestion (I'm so impatient ^^). As the parent class is instantiated by a factory the change to shared_ptr didn't have a lot of side effects. Thanks again! – Managarm Sep 13 '16 at 15:59