7 ms·
If you've ever wondered what's the deal with C++ and why it's being used in 2013, you might wanna watch this. Stroustrup isn't a very flashy speaker, but he say
by fhd2 13y ago
If you've ever wondered what's the deal with C++ and why it's being used in 2013, you might wanna watch this. Stroustrup isn't a very flashy speaker, but he says some incredibly insightful things.
C++'s C heritage makes it hard to master and also causes countless misconceptions. Even if you never want to use C++, it's worth looking into some of the unique concepts that, sadly, didn't catch on in other languages so far. (My personal favourites are const correctness and RAII.)
Do watch the talk, the first few minutes might already be mind blowing for anyone who thought C and C++ are basically the same language.
- fauigerzigerk 13y agoThere 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.
- epsylon 13y ago> C++'s C heritage Well, at this point it's more like C++'s C++ heritage. > const correctness It certainly exists in plenty of other languages, but in a non-broken way. C++'s const correctness model is mostly broken, by the way [1]. D's model is a bit more sane [2]. Languages like Haskell or Clojure (AFAIK) make immutability a default. This kind of functional style is a good thing for C++ developers overall, as emphasized by John Carmack [3]. [1] Once again, the C++ FQA has plenty of wisdom to share: http://yosefk.com/c++fqa/const.html http://yosefk.com/c++fqa/const.html [2] http://en.wikipedia.org/wiki/Const-correctness#const_and_immutable_in_D http://en.wikipedia.org/wiki/Const-correctness#const_and_imm... [3] http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/ http://www.altdevblogaday.com/2012/04/26/functional-programm... > RAII didn't catch in other languages That's because most other languages are garbage collected. (Not that RAII is a bad thing, it's just not needed.)
- fhd2 13y ago> It certainly exists in plenty of other languages, but in a non-broken way. C++'s const correctness model is mostly broken, by the way [1]. D's model is a bit more sane [2]. Languages like Haskell or Clojure (AFAIK) make immutability a default. What in particular is broken about const correctness in C++? That things are not const by default? I agree, they should be, but I wouldn't really call that broken. I put const wherever I can, just like Carmack. So I sort of pretend it's the default :) I don't think it makes sense to compare const correctness in C++ to immutability in Clojure. In Clojure, you don't have objects that encapsulate internal state. const in C++ allows you to say which methods do change internal state and which don't. If you pass a const reference, the receiver can only call const methods. I just learned from you that D has this, wasn't aware of any other OOP language that has it. Not even Scala :( > That's because most other languages are garbage collected. (Not that RAII is a bad thing, it's just not needed.) RAII is about more than just memory, it's about any kind of resource. That includes stuff like file handles, Java's try {} finally {} is IMO a weird workaround. In C++, stream's can just close themselves when they go out of scope.
- epsylon 13y ago> What in particular is broken about const correctness in C++? The lack of transitivity for one. Const pointers shouldn't be able to modify the pointed objects (that's the default in the D language). The fact that working with non-const-correct libraries is a nightmare (prepare to const_cast a lot!). There are plenty of other things that make this a real PITA to work with on sizable projects with legacy or outside code. > RAII is about more than just memory, it's about any kind of resource. That's true, yeah, though most of the time it's about memory (with smart pointers). But you're absolutely right on that point. As far as I know, Common Lisp users have some kind of RAII with macros, but I'm not familiar enough to compare it to C++. Of course, D also has support for this idiom.
- dustingetz 13y agoConst correctness is the essence of all functional languages; RAII is in functional languages too and even java has an interface for it