49

I've seen people use a trailing underscore for member variables in classes, for instance in the renowned C++ FAQ Lite.

I think that it's purpose is not to mark variables as members, that's what "m_" is for. It's actual purpose is to make it possible to have an accessor method named like the field, like this:

class Foo {
public:
    bar the_bar() { return the_bar_; }
private:
    bar the_bar_;
}

Having accessors omit the "get_" part is common in the STL and boost, and I'm trying to develop a coding style as close to these as possible, but I can't really see them using the underscore trick. I wasn't able to find an accessor in STL or boost that would just return a private variable.

I have a few questions I'm hoping you will be able to answer:

  1. Where does this convention come from? Smalltalk? Objective-C? Microsoft? I'm wondering.
  2. Would I use the trailing underscore for all private members or just as a workaround in case I want to name a function like a variable?
  3. Can you point me to STL or boost code that demonstrates trailing underscores for member variables?
  4. Does anybody know what Stroustrup's views on the issue are?
  5. Can you point me to further discussion of the issue?
artm
  • 17,291
  • 6
  • 38
  • 54
eomer
  • 563
  • 1
  • 5
  • 7
  • 1
    For point 4 refer http://www2.research.att.com/~bs/bs_faq2.html – Chubsdad Sep 06 '10 at 10:17
  • 2
    @Nick D: How can that be a duplicate, did you read it? It asks a completely unrelated question, i.e. if a leading (!) underscore is legal in C++. – eomer Sep 06 '10 at 10:22
  • @chubsdad: I've read that, but he doesn't really mention trailing underscore or accessors. He merely states that he dislikes classes with many get/set functions. – eomer Sep 06 '10 at 10:26
  • For point 3 there is an example in boost/asio/ssl/stream.hpp for member next_layer_ – usta Sep 06 '10 at 13:41
  • I also found some 'exposition only' data members named with a trailing underscore in the standard :) – usta Sep 06 '10 at 13:49
  • Here they are: sbuf_ (24.5.3, 24.5.3.1, 24.5.4), ok_ (27.6.1.1.2, 27.6.2.3), keep_ (24.5.3.1) – usta Sep 06 '10 at 13:57
  • @usta: Where did you find them? – eomer Sep 07 '10 at 08:10
  • @eomer Sorry if I was not clear enough. I found those in the International C++ Standard, ISO/IEC 14882:2003 – usta Sep 07 '10 at 12:16
  • I saw this convention used in http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml – mihaipopescu May 29 '12 at 19:17

7 Answers7

40

In C++,

  1. identifiers starting with an underscore, followed by a capital character
  2. identifiers having two consecutive underscores anywhere
  3. identifiers in the global namespace starting with an underscore

are reserved to the implementation. (More about this can be found here.) Rather than trying to remember these rules, many simply do not use identifiers starting with an underscore. That's why the trailing underscore was invented.

However, C++ itself is old, and builds on 40 years of C (both of which never had a single company behind them), and has a standard library that has "grown" over several decades, rather than brought into being in a single act of creation. This makes for the existence of a lot of differing naming conventions. Trailing underscore for privates (or only for private data) is but one, many use other ones (not few among them arguing that, if you need underscores to tell private members from local variables, your code isn't clear enough).

As for getters/setters - they are an abomination, and a sure sign of "quasi classes", which I hate.

sbi
  • 219,715
  • 46
  • 258
  • 445
  • 6
    I'm with you there, I avoid getters/setters wherever possible. But sometimes, they are actually useful - especially when using GOF design patterns. A simple example: Consider a class that owns and initialises objects (like the graphics subsystem in a game engine) and allows other classes access them. I'd use an accessor method, because declaring the variable public would allow read/write access, while I only want to allow read access. I can also return a const reference to ensure const correctness when using an accessor. – eomer Sep 06 '10 at 12:51
16

I've read The C++ Programming Language and Stroustrup doesn't use any kind of convention for naming members. He never needs to; there is not a single simple accessor/mutator, he has a way of creating very fine object-oriented designs so there's no need to have a method of the same name. He uses structs with public members whenever he needs simple data structures. His methods always seem to be operations. I've also read somewhere that he disencourages the use of names that differ only by one character.

forceal
  • 673
  • 1
  • 6
  • 8
  • 5
    What about, say, `std::vector::size()`? I imagine it could contain a `size_` member. – claymation May 03 '15 at 18:57
  • 5
    "He uses structs with public members whenever he needs simple data structures." That dangerous renegade! (+1) – underscore_d Sep 19 '15 at 20:38
  • 1
    @claymation, the size might need to be computed (e.g. fast linked list that does not store an element count) occasionally, but insertions are frequent. The read-increment-store might be too much overhead for a value that is never needed. – jbruni Oct 29 '19 at 20:41
13

I am personally a big fan of this guideline: http://geosoft.no/development/cppstyle.html

It includes omitting the m_ prefix, using an underscore suffix to indicate private member variables and dropping the horrid, annoying-to-type habit of using underscores instead of space, and other, more detailed and specific suggestions, such as naming bools appropriately(isDone instead of just done) and using getVariable() instead of just variable() to name a few.

identity
  • 949
  • 6
  • 14
  • 8
    Well most of this stuff is just personal aesthetic preference, up to the point that [this](http://www.amazon.com/Coding-Standards-Rules-Guidelines-Practices/dp/0321113586) great Coding Standard subsumes all of this as: 0. Don't sweat the small stuff. (Or: know what not to standardize.) ... Just be consistent. – Fabio Fracassi Sep 06 '10 at 12:17
  • 1
    I also prefer not to use `[get|compute]Data()`, because code like `use( texture.data() );` reads much nicer IMVHO, and doesn't distract the class user with details he shouldn't care about like whether the data is cached or needs to be computed. – Fabio Fracassi Sep 06 '10 at 12:21
  • 12
    I think `is_done` reads much better than `isDone`. `_` is much more like a space than no space at all. – GManNickG Sep 06 '10 at 16:36
  • 1
    It's interesting that this style guide recommends stuff that is not used anywhere in the STL. For example, camel-case type names. – jbruni Oct 29 '19 at 20:47
  • Is there an add-on for cppcheck, regarding geosoft cpp style?? – Melroy van den Berg Dec 30 '21 at 00:14
11

Only speaking for myself... I always use trailing underscore for private data members, regardless if they have accessor functions or not. I don't use m_ mainly because it gets in the way when I mentally spell the variable's name.

usta
  • 6,699
  • 3
  • 22
  • 39
  • 3
    Agree and go further - I use a trailing underscore with any private symbol (in C++ and Java), and find the 'm_' an abomination (leftover of Hungarian notation). The underscore allows the "same" names to be used in private and non-private contexts, where that name is the most appropriate. – simon.watts Jun 12 '18 at 12:00
5

As a maintenance developer that likes searchability I'm leaning towards m_ as its more searchable. When you, as me, are maintaining big projects with large classes (don't ask) you sometimes wonder: "Hmmm, who mutates state?". A quick search for m_ can give a hint.

I've also been known to use l_ to indicate local variables but the current project doesn't use that so I'm "clean" these days.

I'm no fan of hungarian notation. C++ has a strong type system, I use that instead.

  • Fwiw, in addition to `m_`, I prefix `s_` to static class members/methods and `d_` to the derived implementations when using CRTP. I've never tried denoting locals vs parameters by using `l_`/`p_`... and kinda hope I don't as it'd be a lot of work to change. :P – underscore_d Sep 19 '15 at 20:39
4

I'm guessing that utopia would have been to use a leading underscore - this is quite common in Java and C# for members.

However, for C, leading underscores aren't a good idea, so hence I guess the recommendation by the C++ FAQ Lite to go trailing underscore:

All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.


(ISO C99 specification, section 7.1.3)

StuartLC
  • 104,537
  • 17
  • 209
  • 285
1

As far as I remember, it's not Microsoft that pushed the trailing underscore code style for members.

I have read that Stroustrup is pro the trailing underscore.

Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
  • Do you remember where you read that? I'd be pretty interested because it is always interesting to read Stroustrup's reasoning. – eomer Sep 06 '10 at 11:43
  • ok let me sometime to remember ;-), I am almost sure it's on his website, but I should check. – Stephane Rolland Sep 06 '10 at 11:45
  • 16
    "It gives me all info at once" - until someone changes the type and forgets to update the pseudoHungarian tags. Then they stop being useful and become actively harmful. – Mike Seymour Sep 06 '10 at 11:52
  • 5
    http://en.wikipedia.org/wiki/Hungarian_notation: quotation from Bjarne: "No I don't recommend 'Hungarian'. I regard 'Hungarian' (embedding an abbreviated version of a type in a variable name) a technique that can be useful in untyped languages, but is completely unsuitable for a language that supports generic programming and object-oriented programming—both of which emphasize selection of operations based on the type an arguments (known to the language or to the run-time support). In this case, 'building the type of an object into names' simply complicates and minimizes abstraction" – Stephane Rolland Sep 06 '10 at 11:54
  • 1
    The big problem with Hungarian Notation is where you have to change the type, you're forced to update your source wherever that variable resides while this is easy in most editors, it can detract from the reviewer's attention when looking at diffs. – johnsyweb Sep 06 '10 at 11:55
  • 4
    @Stephane: That quote is not really about underscores, is it? – eomer Sep 06 '10 at 11:57
  • @Mike maybe. As for me it means two things: If the modifier did not update the variable name: 1/ He is lazy and doesnt bother writing code that is understandable. 2/ There are too much occurence of the variable everywhere and this implied the variable is public and not accessed through an accessor. – Stephane Rolland Sep 06 '10 at 11:57
  • @eomer, no the Hungarian notation it the way for writing `IUnknown * m_pUnknown;` and Bjarne is against ( but you are right he doesnt say he is for the for the trailing underscore, though I thought there was only those two main trends for coding style ) – Stephane Rolland Sep 06 '10 at 11:59
  • @Stephane There is also the possibility of not using any special naming style, just "foo" instead of "foo_" or "m_foo" or whatever. That's what Bjarne does in "The C++ Programming Language". – eomer Sep 06 '10 at 12:04
  • @eomer, there I have found this paper, about the GNU C++ style, and he is for the trailing underscore. http://www.scribd.com/doc/3020505/C-Programming-Style-Guidelines I don't know him, Fred Richards, and haven't read the entire text so I don't know what it's worth. – Stephane Rolland Sep 06 '10 at 12:09
  • 1
    minus 1 for the focus on your off-topic personal preference for (needless, risky) Hungarian, written in a way that falsely implies Stroustrup favours it. – underscore_d Sep 19 '15 at 20:37
  • @underscore_d that's right, I changed my mind since... I can use Hungarian notation, as much as I can choose not to use it. However I don't consider it "needless and risky". I edited the answer accordingly. – Stephane Rolland Sep 19 '15 at 20:58