C++ Idioms by Example

I read a lot of code. Often I like what I see, but sometimes I see code that is perfectly OK according to the definition of the language but which is flawed because it breaks too many established idioms and conventions of the language. There are plenty of really good books about this topic, but most of them start at a slightly too advanced level – they assume that the reader already know about the basic stuff.

I have tried to make a little contribution by illustrating some of the really basic C++ idioms and conventions using a contrived but still complete example. Please take a look at this presentation.

When presenting this stuff, I usually hand out the first code snippet to a group of people, then I do online coding while the group suggests improvements and we discuss why it is so. Interesting enough, it seems like we always end up roughly at the same place. This presentation is just one of several paths that might happen when a group decides what to improve or not.

13 Responses to C++ Idioms by Example

  1. bjorn says:

    “28. avoid side-effects if you can, prefer free-standing functions” isn’t obvious to me. I prefer a `.doSomthing()` to a `.getValue()` any day.

  2. Jonathan Wakely says:

    #17 assuming you mean deprecated rather than depreciated, since when?

    #19, assigning a string literal to a char* isn’t only bad style because it implies the string might change, it will also lead to undefined behaviour if someone actually tries to change it. Using const char* not only makes the intention clear, but avoids undefined behaviour, which is more important IMHO.

    #22 Although a return statement is not required in main() I would say it’s better style to include it.

    #29 why not?

    #32 I expected to see this point much sooner, this is a correctness issue, not just style.

    #33 really? :-)

    • Alan Stokes says:

      Jonathan:

      #29 – if you declare bar(int) in namespace foo, then accidentally define bar(long) in the same namespace, no error occurs (until link time, if you try to call bar(int)). But if you try to define foo::bar(long) outside the namespace you’ll get a nice hard compile error immediately.

      So defining functions outside their declared namespace is a useful habit, at least.

      #33 – quite agree. I use 8 spaces. Makes it really hard to have deep nesting – which is good.

  3. I like most of those. The one that I really lean away from, though, is using anonymous namespaces for private free standing functions. That effectively renders them unmockable. Isn’t always a big deal, but often it is hard to know whether someone may need to mock something or not.

  4. I like the idea and content. But I’m a little distracted by the my_magic/myMagic implementation. Isn’t calc supposed to be:

    value *= 2;
    value += number;

    This makes me see more trouble than the indents and stuff.

  5. stalker says:

    Everything is ok and makes a good points, but #3,#8, #21, #27 are just nonsense. I could argue now for every of them, but we all know code style is tough matter, religion-like. BTW, can you support #21 with any references?

  6. prabodh20 says:

    It is really a good and very helpful

  7. SPB says:

    Most of these are alright, some are rubbish. I’m not sure the author knows *why* some of these have become ‘common idioms’ though. Example: the for loop’s change from i++ to ++i is often done because there’s a small performance hit with the postfix increment (due to the allocation of a temporary variable) as opposed to the prefix increment.

    Additionally, these don’t go far enough. This code still wouldn’t pass a code review w/ me. I’d require that the for loop be rewritten using the standard library’s for_each method. I’d also ditch the use of char* in favor of std::string (or a String class from a library we’re using such as QString). Last, prefer passing by reference over passing by pointer. If you pass by const &, you can avoid a call to the object’s copy constructor as well as guarantee against runtime change to object state.

  8. Liam Sharp says:

    Like most of this…

    #3 This looks very odd with pointers:

    foo_->bar(); // Yuk
    m_foo->bar(); // Now I can search in my editor for “m_” :-)

    #6 Be good to explain why?

    #19 std::string ?

    #21. “In C++” we use std::for_each – I’d be interested in the background behind your suggestion?

    #22 “do not need to explicitly” – that does not mean you shouldn’t!

    #27 Is short hand for ‘insert bug here!’. I’ve lost count of the times I’ve seen this. Use the braces, make it clear, make it explicit.

  9. Bill Penney says:

    I used this presentation today for an internal training session: although we didn’t agree with all of it, it made an excellent forum for discussion and we got a lot out of the arguments that followed!

    Thanks, Olve.

  10. Techno John says:

    33. real professionals indent by 4 spaces?

    err, I think you’ll find they follow the company coding style, regardless of their personal preference. That’s what professional means.

  11. iresha says:

    This was really useful. There are many things I didn’t know

  12. Alan Ning says:

    Some stuff in the presentations are useful, some are just style issues.

    For example, putting a space around & and * is really a matter of taste. It adds nothing to correctness. I wouldn’t classify it as an “idiom”.