4 ms·
There are also some things that are powerful but I'm not quite sure if I really like them. For instance, he promotes the use of handles instead of pointers. He
by fauigerzigerk 13y ago
There are also some things that are powerful but I'm not quite sure if I really like them. For instance, he promotes the use of handles instead of pointers. He goes through these variants:
Gadget* p = new Gadget(n); // not exception safe
shared_ptr<Gadget> p{new Gadget(n)}; //exception safe
unique_ptr<Gadget> p{new Gadget(n)}; //exception safe and less wasteful than shared_ptr if local
Gadget g{n}; //his preferred solution
My problem with his preferred solution is that I cannot know that Gadget is really a handle to a shared Gadget and not a big fat Gadget value on the stack. The only way of knowing that is to look at the implementation or the documentation.
So if g is returned from a function or passed to a function by value, I don't know whether or not a deep copy is made. If I manipulate that Gadget, am I manipulating a shared object affecting others or is this my private copy?
Qt uses that pattern throughout, and because it is used for everything in Qt, you know that you're dealing with handles. But the C++ standard library doesn't do it that way. Almost none of the classes in the standard library are handles.
If I see a pointer, shared or otherwise, I know I'm not dealing with a deep copy. I know someone somewhere else might point to the same object.
- T-zex 13y agoC++11 move semantics eliminates the need of deep copying in most cases and return by value usually is very cheap.
- fauigerzigerk 13y agoBut move semantics only work with temporaries. They don't magically make every object a handle.
- marshray 13y agoFor that, there's Java.
- fhd2 13y ago> My problem with his preferred solution is that I cannot know that Gadget is really a handle to a shared Gadget and not a big fat Gadget value on the stack. The only way of knowing that is to look at the implementation or the documentation. I'd say you do not _need_ to know. If Gadget contains tons of data, it's wiser for it to just put that on the heap, internally. Like std::vector does. As long as Gadget handles (or forbids) copying, assigment etc. (rule of three), that's fine. If you do have a huge performance issue because you're using a class that, unwisely, puts tons of data on the stack, you can use a unique_ptr instead. Kind of an edge case in my experience though.
- fauigerzigerk 13y agoI disagree. You have to be absolutely certain at all times whether you're holding on to a reference to a shared data structure or you have your own copy, unless the object is immutable. This is not just a performance thing.
- fhd2 13y agoYou mean that it's not clear if copying the handle will copy the data or just create another reference? At least in the STL that's kinda clear: vector will copy its elements (if they are pointers, it'll copy the pointers. if they are values it'll copy all the data), shared_ptr will copy the handle pointing to the same shared object, unique_ptr is not copyable and so on. But agreed, it's opaque when working with third party code. Gotta figure out the conventions.
- fauigerzigerk 13y ago>You mean that it's not clear if copying the handle will copy the data or just create another reference? Exactly. In the STL, if it looks like a value copy it is a value copy, but the handle pattern that Stroustrup prefers gives you no clue whatsoever as to what's going to happen. You have to figure it out one class at a time.
- jasomill 13y agoI'd also say that using any class without reference to either its documentation or its implementation is a terrible idea in the first place, because who cares where it stores data if you're not using it properly? I can't count the number of bugs I've fixed due to programmers (myself, sadly, included) using IDE code completion features as a substitute for reading documentation.
- marshray 13y agoSomehow I don't find this to be a problem in my code. Yes, when using someone else's library you need to know how they handle ownership. But this is basically a problem inherited from C. For example, in the code you posted all the pointer-like handles are named 'p'. In my experience, if we consistently pursue minimal scope and minimal lifetime for our objects, then longer-lived objects are oddballs and we use the type of the handle to help describe its ownership strategy.
- fauigerzigerk 13y agoI agree that this is an issue with third party libraries, not with my own code. But C++ libraries can be a real horror. Every single one of them comes with its own peculiar memory management idea. Recently I started to use rapidjson. It's insanely fast but that's not the only insanity. It basically screams for memory management bugs.
- pjmlp 13y agoEver done any enterprise C development? This is a very big problem in enterprise size code basis, specially with the rotation of external developers.
- marshray 13y agoOh noes. Yeah, C seems very not the thing to rotate external developers around in an enterprise size code base.