There are a few questions here, so bear with me if I donβt address them in the order you expect.
Most SO tips say use shared_ptr, not regular pointers.
Yes and no. Many SO users, unfortunately, recommend shared_ptr as if it were a silver bullet to solve all memory management issues. This is not . Most tips say that they do not use bare pointers, which is significantly different.
The real advice is to use smart managers : smart pointers ( unique_ptr , scoped_ptr , shared_ptr , auto_ptr ), smart containers ( ptr_vector , ptr_map ) or custom solutions for complex tasks (based on Boost.MultiIndex, using intrusive counters, etc.).
You must choose a smart manager to use, as appropriate. Most notably, if you do not need to share ownership of the object, then you should not use shared_ptr .
What is COW?
COW (Copy-On-Write) is about sharing data to "save" memory and simplify copying ... without changing the semantics of the program.
From the user's point of view, whether std::string COW is used or not does not matter. When a row changes, all other rows are not affected.
The idea behind COW is as follows:
- If you are the sole owner of the data, you can change it.
- If you do not, you must copy it and then use a copy
It looks like shared_ptr , so why not?
This is similar, but both are designed to solve different problems, and as a result they are slightly different.
The problem is that since shared_ptr designed to run smoothly regardless of whether it is shared or not, it is difficult for COW to run the "if only owner" test. Remarkably, the weak_ptr interaction weak_ptr it difficult.
Perhaps, obviously. The key is not to leak shared_ptr in general, and not to use weak_ptr (they are still useless for COW).
Does it matter?
No, not at all. It has been proven that COW is not so great. In most cases, itβs micro-optimization ... and micro-pessimization right away. You can get rid of some memory (although it only works if you do not copy large objects), but you complicate the algorithm, which can slow down the execution (you enter tests).
My advice is not to use COW. And do not use those shared_ptr .
Personally, I would like to:
- use
boost::ptr_vector<Ingredient> , not std::vector< boost::shared_ptr<Ingredient> > (you don't need sharing) - create an
IngredientFactory that will create (and manage) the ingredients and return Ingredient const& Factory must survive any Receipt .
EDIT : after a comment by Xeo, it seems the last element ( IngredientFactory ) is pretty concise ...
In the case of an IngredientFactory the Receipt object will contain std::vector<Ingredient const*> . Note the raw pointer:
Receipt not responsible for the memory, but gets access to it- there is an implicit guarantee that the specified object will remain valid longer than the
Receipt object
It is good to use raw (bare) pointers if you treat them as if you were referencing. You just need to beware of potential invalidity, and you are offered the opportunity to reinstall them if you wish, and you trust the provider to take care of lifecycle / memory management aspects.