6 ms·
I’ve personally never encountered the particular misunderstanding the author dispels here, but I’m sure the post is written from bitter experience. On the one h
by codeflo 6y ago
I’ve personally never encountered the particular misunderstanding the author dispels here, but I’m sure the post is written from bitter experience. On the one hand, I shouldn’t be that surprised: Unfortunately, programming in C++ is really brutal for people who would rather learn by example than by carefully reading documentation.
But on the other hand, my instinctive reaction is: Come on, is this really something that confuses people? emplace_back is all about constructing something in-place, which is exactly the opposite of moving it there! How can any professional programmer be 180 degrees wrong about the purpose of a function they use regularly?
What I want to say here is that C++ is really hard, and that there are a million subtle things that one simply has to look up instead of making educated guesses. I don’t think people appreciate this difficulty enough.
- mettamage 6y agoI learn C++ by example by using the VSCode debugger. I prefer it over gdb with tui. It won’t go all the way (e.g. educational/smallish projects only that are single threaded) but by that time a programmer has seen some wonky things happening that they can hypothesize about. In my case: - dangling pointers - integer under/overflow - macro expansion (not via debugger but VSCode helps with this) - double values not being the same when you expect them to be the same - Seeing if something is copied or moved [1] [1] Not sure if this is actually true. But I think it can be true by simply stepping inside the function like emplace_back
- vbezhenar 6y agoIf you're using Linux, run your test programs under valgrind. It'll help you immensely to find memory issues.
- readams 6y agoI mostly use address sanitizer these days rather than valgrind. It's fast enough that you can just put it in your default compile flags for debugging.
- scatters 6y agoAnd it's available for Visual Studio, so you don't even need to be running Linux.
- junon 6y agoAddress sanitizers have bitten me before. Valgrind has not, aside from the times it wasn't supported on new macos. Just be careful.
- usefulcat 6y agoIt is faster, but IME valgrind is more thorough. I have an option to run unit tests with valgrind.
- xKingfisher 6y agoThe article did touch on a possible reason for the misunderstanding. If you already know from previous versions that push_back makes a copy and that C++11 added move semantics and emplace_back, it's not a huge leap to connect the two. Especially if you don't notice push_back's rvalue overload (or understand rvalues). And if you're new to C++ and are having all of this thrown at you at once it'd definitely be easy to get some crossed wires.
- brown9-2 6y agoAs someone new to C++, it seems endlessly confusing that you are supposed to know if a function call is making a copy vs a move by figuring out the signature of the function being called or knowing which one the compiler picks, rather than being explicit about it in the code (with std::move or somehow annotating the call with what you want).
- xKingfisher 6y agoIt's definitely a lot to process. I found these two articles really helpful when trying to understand moves: https://abseil.io/tips/55 https://abseil.io/tips/55 https://abseil.io/tips/77 https://abseil.io/tips/77 Though I'd also say don't worry about it too much, especially at first. If you're copying a lot of temporary objects moving can get you some performance wins, but that's something profiling should be telling you m
- jeffbee 6y agoAuthors should also try to be aware that for some types there's not a meaningful difference between copy construction and move construction.
- junon 6y agoYou should always know the signature of a function you're calling. Please be reading docs. The part I agree with are the method selection semantics. A good rule of thumb (though don't rely on it) is that the "more specific" prototype generally wins.
- npsimons 6y ago> What I want to say here is that C++ is really hard, and that there are a million subtle things that one simply has to look up instead of making educated guesses. I don’t think people appreciate this difficulty enough. Very much so. I tell everyone not to bother learning C++, there are so many other better languages out there. Hell, I'm only still using it because of legacy projects
- oconnor663 6y ago> How can any professional programmer be 180 degrees wrong about the purpose of a function they use regularly If you have a strong understanding of move semantics, then I agree it would be pretty weird to misunderstand the relationship between move semantics and emplace_back. But how common is it to have a strong understanding of move semantics, really? Can we confidently assume that even 50% of professional C++ programmers have a strong understanding of move semantics? I've known competent C++ devs, who write template metaprograms for fun, who were still surprised to learn basic facts about move semantics like "the destructor of a moved-from object will still be called." I know for certain that I don't have a strong understanding of move semantics, but I wouldn't call myself a C++ programmer either, so at least I'm not dragging down the statistics :)
- wnissen 6y agoYes, I think his recommendation to prefer push_back is wrong for that reason. I can't imagine it's easier for the compiler to reason about std::move and destructors compared to inlining the constructor.
- ncmncm 6y agoNope, he's right. He maybe shouldn't be right, but certain convenience features are still missing from Standard Library components and the language that could someday make him wrong. It is sometimes right to hold your nose and use std::piecewise_construct. But most usually it doesn't matter, and worrying about it will distract you from what does matter. So, push_back() unless you know you have a good reason not to. And, you might never encounter one. Good C++ and naïve C++ are not so different. Both are much better than fake-smart C++.
- jdashg 6y ago> Unfortunately, programming in C++ is really brutal for people who would rather learn by example than by carefully reading documentation. This is a great observation! There's probably a ton of this that feeds the "$lang/api/framework is garbage"/"no it's not" schisms. "Well do you prefer documentation or a REPL?"
- whatshisface 6y ago"A manual is a human-operated type system."
- DougBTX 6y agoIn some languages the documentation is available as essentially a property of the documented object, so pulling up docs in the repl is easy. It isn’t quite a binary choice.
- umvi 6y ago> C++ is really brutal for people who would rather learn by example than by carefully reading documentation As if the documentation/compiler implementations are otherwise perfect. Quick, does `std::condition_variable::wait_for` use a monotonic clock under the hood? Here's the docs: https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for https://en.cppreference.com/w/cpp/thread/condition_variable/... You might think so based on the part that says: > Note that rel_time must be small enough not to overflow when added to std::chrono::steady_clock::now()." But I happen to know from actually using it, that not all implementations use a monotonic clock: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861 This led to a rather dramatic time bomb bug in our code that only flared up when GPS (and therefore system time) was being spoofed to replay a specific scenario in the past.