Confusion about Copy-On-Write and shared_ptr?

There are several questions bundled into one here, so bear with me if I don't address them in the order you would expect Most advice on SO says to use shared_ptr rather than regular pointers Yes and No. A number of users of SO, unfortunately, recommend shared_ptr as if it were a silver bullet to solve all memory management related issues It is not Most advice talk about not using naked pointers, which is substantially different The real advice is to use smart managers : whether smart pointers ( unique_ptr scoped_ptr shared_ptr auto_ptr ), smart containers ( ptr_vector ptr_map ) or custom solutions for hard problems (based on Boost. MultiIndex, using intrusive counters, etc...) You should pick the smart manager to use depending on the need.

Most notable, if you do not need to share the ownership of an object, then you should not use a shared_ptr What is COW? COW (Copy-On-Write) is about sharing data to "save" memory and make copy cheaper... without altering the semantic of the program From a user point of view, whether std::string use COW or not does not matter. When a string is modified, all other strings are unaffected The idea behind COW is that: if you are the sole owner of the data, you may modify it if you are not, then you shall copy it, and then use the copy instead It seems similar to shared_ptr so why not?

It is similar, but both are meant to solve different problems, and as a result they are subtly different The trouble is that since shared_ptr is meant to function seamlessly whether or not the ownership is shared, it is difficult for COW to implement the "if sole owner" test. Notably, the interaction of weak_ptr makes it difficult It is possible, obviously. The key is not to leak the shared_ptr at all, and not to use weak_ptr (they are useless for COW anyway) Does it matter?

No, not really. It's been proved that COW is not that great anyway. Most of the times it's a micro optimization... and a micro pessimization at once.

You may spare some memory (though it only works if you don't copy large objects), but you are complicating the algorithm, which may slow down the execution (you are introducing tests) My advice would be not to use COW. And not to use those shared_ptr either Personnally, I would either: use boost::ptr_vector.

There are several questions bundled into one here, so bear with me if I don't address them in the order you would expect. Most advice on SO says to use shared_ptr rather than regular pointers. Yes and No.

A number of users of SO, unfortunately, recommend shared_ptr as if it were a silver bullet to solve all memory management related issues. It is not. Most advice talk about not using naked pointers, which is substantially different.

The real advice is to use smart managers: whether smart pointers (unique_ptr, scoped_ptr, shared_ptr, auto_ptr), smart containers (ptr_vector, ptr_map) or custom solutions for hard problems (based on Boost. MultiIndex, using intrusive counters, etc...). You should pick the smart manager to use depending on the need.

Most notable, if you do not need to share the ownership of an object, then you should not use a shared_ptr. What is COW? COW (Copy-On-Write) is about sharing data to "save" memory and make copy cheaper... without altering the semantic of the program.

From a user point of view, whether std::string use COW or not does not matter. When a string is modified, all other strings are unaffected. The idea behind COW is that: if you are the sole owner of the data, you may modify it if you are not, then you shall copy it, and then use the copy instead It seems similar to shared_ptr, so why not?

It is similar, but both are meant to solve different problems, and as a result they are subtly different. The trouble is that since shared_ptr is meant to function seamlessly whether or not the ownership is shared, it is difficult for COW to implement the "if sole owner" test. Notably, the interaction of weak_ptr makes it difficult.It is possible, obviously.

The key is not to leak the shared_ptr, at all, and not to use weak_ptr (they are useless for COW anyway). Does it matter? No, not really.

It's been proved that COW is not that great anyway. Most of the times it's a micro optimization... and a micro pessimization at once. You may spare some memory (though it only works if you don't copy large objects), but you are complicating the algorithm, which may slow down the execution (you are introducing tests).

My advice would be not to use COW. And not to use those shared_ptr either. Personnally, I would either: use boost::ptr_vector rather than std::vector (you do not need sharing) create a IngredientFactory, that would create (and manage) the ingredients, and return a Ingredient const&, the Factory should outlive any Receipt.

EDIT: following Xeo's comment, it seems the last item (IngredientFactory) is quite laconic... In the case of the IngredientFactory, the Receipt object will contain a std::vector. Note the raw pointer: Receipt is not responsible for the memory, but is given access to it there is an implicit warranty that the object pointed to will remain valid longer than the Receipt object It is fine to use raw (naked) pointers, as long as you treat them like you would a reference. You just have to beware of potential nullity, and you're offered the ability to reseat them if you so wish -- and you trust the provider to take care of the lifetime / memory management aspects.

1 Thanks for a well-reasoned and accurate assessment of the problem. – templatetypedef Jun 6 at 8:17 +1 for thoroughness, though I'll offer that I've found some interesting applications for copy-on-write for GUI apps. I force worker threads doing background tasks to pay for the copy of data structures while the GUI thread proceeds...kinda slick: hostilefork.Com/thinker-qt – HostileFork Jun 6 at 8:19 Very nice answer, but you might also want to add that naked pointers are perfectly fine (imho), if you pass them to a function that isn't concerned about ownership at all for example.

– Xeo Jun 6 at 8:38 @Hostile Fork: There are cases where COW makes sense, however it is an optimization trick, and such tricks should only be used when it has been measured they were beneficial :) Thanks for the example (though I don't use QT so I just skimmed over it). – Matthieu M. Jun 6 at 8:43 @Xeo: Thanks.

It was implied in the IngredientFactory idea, I've made it explicit :) – Matthieu M. Jun 6 at 8:49.

You have nothing to worry about. Each Recipe object has its own vector, so modifying one won't affect the other, even though both of them happen to contain pointers to the same objects. The mashed-potatoes recipe would only be affected if you changed the contents of the object that p_milk points at, but you're not doing that.

You're modifying the oatmeal. M_ingredients object, which has absolutely no relation to mashed_potatoes. M_ingredients.

They're two completely independent vector instances.

Most advice on SO says to use shared_ptr rather than regular pointers. Yes and No. A number of users of SO, unfortunately, recommend shared_ptr as if it were a silver bullet to solve all memory management related issues.

It is not. Most advice talk about not using naked pointers, which is substantially different. The real advice is to use smart managers: whether smart pointers (unique_ptr, scoped_ptr, shared_ptr, auto_ptr), smart containers (ptr_vector, ptr_map) or custom solutions for hard problems (based on Boost.

MultiIndex, using intrusive counters, etc...). You should pick the smart manager to use depending on the need. Most notable, if you do not need to share the ownership of an object, then you should not use a shared_ptr.

What is COW? COW (Copy-On-Write) is about sharing data to "save" memory and make copy cheaper... without altering the semantic of the program. From a user point of view, whether std::string use COW or not does not matter.

When a string is modified, all other strings are unaffected. It seems similar to shared_ptr, so why not? It is similar, but both are meant to solve different problems, and as a result they are subtly different.

The trouble is that since shared_ptr is meant to function seamlessly whether or not the ownership is shared, it is difficult for COW to implement the "if sole owner" test. Notably, the interaction of weak_ptr makes it difficult. It is possible, obviously.

The key is not to leak the shared_ptr, at all, and not to use weak_ptr (they are useless for COW anyway). Does it matter? No, not really.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions