Why use prefixes on member variables in C++ classes

128,036

Solution 1

You have to be careful with using a leading underscore. A leading underscore before a capital letter in a word is reserved. For example:

_Foo

_L

are all reserved words while

_foo

_l

are not. There are other situations where leading underscores before lowercase letters are not allowed. In my specific case, I found the _L happened to be reserved by Visual C++ 2005 and the clash created some unexpected results.

I am on the fence about how useful it is to mark up local variables.

Here is a link about which identifiers are reserved: What are the rules about using an underscore in a C++ identifier?

Solution 2

I'm all in favour of prefixes done well.

I think (System) Hungarian notation is responsible for most of the "bad rap" that prefixes get.

This notation is largely pointless in strongly typed languages e.g. in C++ "lpsz" to tell you that your string is a long pointer to a nul terminated string, when: segmented architecture is ancient history, C++ strings are by common convention pointers to nul-terminated char arrays, and it's not really all that difficult to know that "customerName" is a string!

However, I do use prefixes to specify the usage of a variable (essentially "Apps Hungarian", although I prefer to avoid the term Hungarian due to it having a bad and unfair association with System Hungarian), and this is a very handy timesaving and bug-reducing approach.

I use:

  • m for members
  • c for constants/readonlys
  • p for pointer (and pp for pointer to pointer)
  • v for volatile
  • s for static
  • i for indexes and iterators
  • e for events

Where I wish to make the type clear, I use standard suffixes (e.g. List, ComboBox, etc).

This makes the programmer aware of the usage of the variable whenever they see/use it. Arguably the most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers - NULLs, pointer arithmetic, etc), but all the others are very handy.

For example, you can use the same variable name in multiple ways in a single function: (here a C++ example, but it applies equally to many languages)

MyClass::MyClass(int numItems)
{
    mNumItems = numItems;
    for (int iItem = 0; iItem < mNumItems; iItem++)
    {
        Item *pItem = new Item();
        itemList[iItem] = pItem;
    }
}

You can see here:

  • No confusion between member and parameter
  • No confusion between index/iterator and items
  • Use of a set of clearly related variables (item list, pointer, and index) that avoid the many pitfalls of generic (vague) names like "count", "index".
  • Prefixes reduce typing (shorter, and work better with auto-completion) than alternatives like "itemIndex" and "itemPtr"

Another great point of "iName" iterators is that I never index an array with the wrong index, and if I copy a loop inside another loop I don't have to refactor one of the loop index variables.

Compare this unrealistically simple example:

for (int i = 0; i < 100; i++)
    for (int j = 0; j < 5; j++)
        list[i].score += other[j].score;

(which is hard to read and often leads to use of "i" where "j" was intended)

with:

for (int iCompany = 0; iCompany < numCompanies; iCompany++)
    for (int iUser = 0; iUser < numUsers; iUser++)
       companyList[iCompany].score += userList[iUser].score;

(which is much more readable, and removes all confusion over indexing. With auto-complete in modern IDEs, this is also quick and easy to type)

The next benefit is that code snippets don't require any context to be understood. I can copy two lines of code into an email or a document, and anyone reading that snippet can tell the difference between all the members, constants, pointers, indexes, etc. I don't have to add "oh, and be careful because 'data' is a pointer to a pointer", because it's called 'ppData'.

And for the same reason, I don't have to move my eyes out of a line of code in order to understand it. I don't have to search through the code to find if 'data' is a local, parameter, member, or constant. I don't have to move my hand to the mouse so I can hover the pointer over 'data' and then wait for a tooltip (that sometimes never appears) to pop up. So programmers can read and understand the code significantly faster, because they don't waste time searching up and down or waiting.

(If you don't think you waste time searching up and down to work stuff out, find some code you wrote a year ago and haven't looked at since. Open the file and jump about half way down without reading it. See how far you can read from this point before you don't know if something is a member, parameter or local. Now jump to another random location... This is what we all do all day long when we are single stepping through someone else's code or trying to understand how to call their function)

The 'm' prefix also avoids the (IMHO) ugly and wordy "this->" notation, and the inconsistency that it guarantees (even if you are careful you'll usually end up with a mixture of 'this->data' and 'data' in the same class, because nothing enforces a consistent spelling of the name).

'this' notation is intended to resolve ambiguity - but why would anyone deliberately write code that can be ambiguous? Ambiguity will lead to a bug sooner or later. And in some languages 'this' can't be used for static members, so you have to introduce 'special cases' in your coding style. I prefer to have a single simple coding rule that applies everywhere - explicit, unambiguous and consistent.

The last major benefit is with Intellisense and auto-completion. Try using Intellisense on a Windows Form to find an event - you have to scroll through hundreds of mysterious base class methods that you will never need to call to find the events. But if every event had an "e" prefix, they would automatically be listed in a group under "e". Thus, prefixing works to group the members, consts, events, etc in the intellisense list, making it much quicker and easier to find the names you want. (Usually, a method might have around 20-50 values (locals, params, members, consts, events) that are accessible in its scope. But after typing the prefix (I want to use an index now, so I type 'i...'), I am presented with only 2-5 auto-complete options. The 'extra typing' people attribute to prefixes and meaningful names drastically reduces the search space and measurably accelerates development speed)

I'm a lazy programmer, and the above convention saves me a lot of work. I can code faster and I make far fewer mistakes because I know how every variable should be used.


Arguments against

So, what are the cons? Typical arguments against prefixes are:

  • "Prefix schemes are bad/evil". I agree that "m_lpsz" and its ilk are poorly thought out and wholly useless. That's why I'd advise using a well designed notation designed to support your requirements, rather than copying something that is inappropriate for your context. (Use the right tool for the job).

  • "If I change the usage of something I have to rename it". Yes, of course you do, that's what refactoring is all about, and why IDEs have refactoring tools to do this job quickly and painlessly. Even without prefixes, changing the usage of a variable almost certainly means its name ought to be changed.

  • "Prefixes just confuse me". As does every tool until you learn how to use it. Once your brain has become used to the naming patterns, it will filter the information out automatically and you won't really mind that the prefixes are there any more. But you have to use a scheme like this solidly for a week or two before you'll really become "fluent". And that's when a lot of people look at old code and start to wonder how they ever managed without a good prefix scheme.

  • "I can just look at the code to work this stuff out". Yes, but you don't need to waste time looking elsewhere in the code or remembering every little detail of it when the answer is right on the spot your eye is already focussed on.

  • (Some of) that information can be found by just waiting for a tooltip to pop up on my variable. Yes. Where supported, for some types of prefix, when your code compiles cleanly, after a wait, you can read through a description and find the information the prefix would have conveyed instantly. I feel that the prefix is a simpler, more reliable and more efficient approach.

  • "It's more typing". Really? One whole character more? Or is it - with IDE auto-completion tools, it will often reduce typing, because each prefix character narrows the search space significantly. Press "e" and the three events in your class pop up in intellisense. Press "c" and the five constants are listed.

  • "I can use this-> instead of m". Well, yes, you can. But that's just a much uglier and more verbose prefix! Only it carries a far greater risk (especially in teams) because to the compiler it is optional, and therefore its usage is frequently inconsistent. m on the other hand is brief, clear, explicit and not optional, so it's much harder to make mistakes using it.

Solution 3

I generally don't use a prefix for member variables.

I used to use a m prefix, until someone pointed out that "C++ already has a standard prefix for member access: this->.

So that's what I use now. That is, when there is ambiguity, I add the this-> prefix, but usually, no ambiguity exists, and I can just refer directly to the variable name.

To me, that's the best of both worlds. I have a prefix I can use when I need it, and I'm free to leave it out whenever possible.

Of course, the obvious counter to this is "yes, but then you can't see at a glance whether a variable is a class member or not".

To which I say "so what? If you need to know that, your class probably has too much state. Or the function is too big and complicated".

In practice, I've found that this works extremely well. As an added bonus it allows me to promote a local variable to a class member (or the other way around) easily, without having to rename it.

And best of all, it is consistent! I don't have to do anything special or remember any conventions to maintain consistency.


By the way, you shouldn't use leading underscores for your class members. You get uncomfortably close to names that are reserved by the implementation.

The standard reserves all names starting with double underscore or underscore followed by capital letter. It also reserves all names starting with a single underscore in the global namespace.

So a class member with a leading underscore followed by a lower-case letter is legal, but sooner or late you're going to do the same to an identifier starting with upper-case, or otherwise break one of the above rules.

So it's easier to just avoid leading underscores. Use a postfix underscore, or a m_ or just m prefix if you want to encode scope in the variable name.

Solution 4

I prefer postfix underscores, like such:

class Foo
{
   private:
      int bar_;

   public:
      int bar() { return bar_; }
};

Solution 5

Lately I have been tending to prefer m_ prefix instead of having no prefix at all, the reasons isn't so much that its important to flag member variables, but that it avoids ambiguity, say you have code like:

void set_foo(int foo) { foo = foo; }

That of cause doesn't work, only one foo allowed. So your options are:

  • this->foo = foo;

    I don't like it, as it causes parameter shadowing, you no longer can use g++ -Wshadow warnings, its also longer to type then m_. You also still run into naming conflicts between variables and functions when you have a int foo; and a int foo();.

  • foo = foo_; or foo = arg_foo;

    Been using that for a while, but it makes the argument lists ugly, documentation shouldn't have do deal with name disambiguity in the implementation. Naming conflicts between variables and functions also exist here.

  • m_foo = foo;

    API Documentation stays clean, you don't get ambiguity between member functions and variables and its shorter to type then this->. Only disadvantage is that it makes POD structures ugly, but as POD structures don't suffer from the name ambiguity in the first place, one doesn't need to use it with them. Having a unique prefix also makes a few search&replace operations easier.

  • foo_ = foo;

    Most of the advantages of m_ apply, but I reject it for aesthetic reasons, a trailing or leading underscore just makes the variable look incomplete and unbalanced. m_ just looks better. Using m_ is also more extendable, as you can use g_ for globals and s_ for statics.

PS: The reason why you don't see m_ in Python or Ruby is because both languages enforce the their own prefix, Ruby uses @ for member variables and Python requires self..

Share:
128,036

Related videos on Youtube

VoidPointer
Author by

VoidPointer

Updated on April 27, 2022

Comments

  • VoidPointer
    VoidPointer about 2 years

    A lot of C++ code uses syntactical conventions for marking up member variables. Common examples include

    • m_memberName for public members (where public members are used at all)
    • _memberName for private members or all members

    Others try to enforce using this->member whenever a member variable is used.

    In my experience, most larger code bases fail at applying such rules consistently.

    In other languages, these conventions are far less widespread. I see it only occasionally in Java or C# code. I think I have never seen it in Ruby or Python code. Thus, there seems to be a trend with more modern languages to not use special markup for member variables.

    Is this convention still useful today in C++ or is it just an anachronism. Especially as it is used so inconsistently across libraries. Haven't the other languages shown that one can do without member prefixes?

    • Joe
      Joe almost 15 years
      I prefer it; in complex codebases it can be important to know which vars are local and which aren't. I generally use the prefix over forcing this-> which I find to be a lot of extra typing and optional (whereas naming will force you to do it)
    • Steve Jessop
      Steve Jessop almost 15 years
      You've never seen it in Ruby because of @ for attribute, and the idiom of generating accessors in preference to using attributes directly.
    • Nathan Osman
      Nathan Osman about 11 years
      According to PEP 8 non-public member variables are to be prefixed with an underscore in Python (example: self._something = 1).
    • too
      too almost 9 years
      Shouldn't editor's syntax highlighting be used to identify these?
    • matec
      matec about 8 years
      You do have seen the equivalent of this->member in Python code. In Python it would typically be self.member and it is not only a convention, it is required by the language.
    • Kostiantyn Ponomarenko
      Kostiantyn Ponomarenko almost 6 years
      This may be interesting for you: github.com/isocpp/CppCoreGuidelines/blob/master/…
    • mosegui
      mosegui over 2 years
      The use of this->memberVar is not just a matter of style. The C++ standard establishes that non-dependent members are not searched for in dependent classes. That means that if you are in a child class trying to access a member variable defined in a parent class template, you will have to either provide a qualified name for that variable BaseClass<FooBar>::memberVar or, if the variable type might depend on the specific instantiation, you might end up with no choice but to access it over the specific class instance this->memberVar. See e.g. stackoverflow.com/a/24368629/4276112
  • Admin
    Admin almost 15 years
    Actually, both _foo and _l are reserved at namespace scope.
  • rmeador
    rmeador almost 15 years
    the compiler can resolve it anyways... local variables will hide ones in higher scope in most langauges. It's for the (dubious) benefit of the humans reading the code. Any decent IDE will highlight locals/members/globals in different ways so there's no need for this sort of stuff
  • Juan
    Juan almost 15 years
    But they are ok as member variable names. I don't prefix underscores, because the rules are too confusing, and I had gotten burned in the past.
  • aroon65
    aroon65 almost 15 years
    Exactly. Locals will hide class members. Consider a constructor that sets these members. Usually it makes sense to name the parameters the same as the members.
  • Martin Beckett
    Martin Beckett almost 15 years
    The problem with using m, rather than m_ (or _) is with the current fashion for camel case it makes it difficult to read some variable names.
  • Admin
    Admin almost 15 years
    I have a cunning plan for dealing with that - I don't use camel case.
  • sbi
    sbi almost 15 years
    If you have a big method, for better clearness break it down.
  • VoidPointer
    VoidPointer almost 15 years
    This very much reflects my on feeling about this issue. Code should be readable without resorting to prefixes. Maybe we don't see so much prefix uses in more modern languages because their user communities have embraced readability a bit more than what you sometimes see in C++. Of course, C++ can and should be readable. It's just that a lot of unreadable C++ has been written over the years.
  • josesuero
    josesuero almost 15 years
    how so? The destructor doesn't have access to local variables declared in other functions, so there's no room for confusion there. Besides, heap-allocated local variables shouldn't exist. And heap-allocated member variables should only exist inside RAII classes, pretty much.
  • Ed S.
    Ed S. almost 15 years
    Exactly why I use 'm_'. I don't like locals with the same name as my member vars.
  • josesuero
    josesuero almost 15 years
    I just don't create locals with the same names as member vars in the first place. If they exist, it's a pretty good hint that your code needs to be refactored.
  • Steve Broberg
    Steve Broberg almost 15 years
    There are lots of reasons not to break down some big methods. For example, if your method needs to keep a lot of local state, you either have to pass lots of parameters into your subordinate methods, create new classes that exist solely for the purpose of passing data between these methods, or declaring the state data as member data of the parent class. All of these have problems that would affect the clarity or maintainability of the method, compared to a single long-ish method (especially one whose logic is straightforward).
  • Admin
    Admin almost 15 years
    @jalf and I should have said multi word class/function names like this: DepositBankAccount.
  • aroon65
    aroon65 almost 15 years
    Why is that a code smell? I'd say it's perfectly common and reasonable, especially when it comes to constructors.
  • Ed S.
    Ed S. almost 15 years
    @jalf: That is not true at all. How about a class that has a "Name" property? In the constructor, I want that info, so I take a parameter called... "name"! Oh wait, my member variable that backs "Name" is called "name". Why does that need refactoring?
  • Pavel Minaev
    Pavel Minaev almost 15 years
    A constructor should (generally) set locals in its initialization list. And there, parameters don't shadow field names, but both are accessible - so you can write struct Foo { int x; Foo(int x) : x(x) { ... } };
  • Steve Jessop
    Steve Jessop almost 15 years
    I assume the problem with that comes when you do Foo(int x, bool blee) : x(x) { if (blee) x += bleecount; } // oops, forgot this-> I prefer to call my member variables something useful and then give constructor parameters that match them abbreviated names: Foo(int f) : foo(f) {...}
  • Admin
    Admin almost 15 years
    Not unless he explains why the underscore. I'm a big fan of his "Rapid Development" book, which I've recommended here numerous times, but much less of "Code Complete" (which I will admit I haven't read since it first came out).
  • Rob
    Rob almost 15 years
    Me too. I also give accessors/mutators the same name.
  • mmmmmmmm
    mmmmmmmm almost 15 years
    @neil: What is "DepositBankAccount" if it isn't camel case?
  • mmmmmmmm
    mmmmmmmm almost 15 years
    @Pavel: Constructors should do so, but they can't always. For example it could be that there is no copy constructor in the type you use and you have to copy by hand inside your constructor body.
  • Admin
    Admin almost 15 years
    I thoght camel case was "depositBankAccount". Or am I getting confused?
  • frankster
    frankster almost 15 years
    "heap-allocated local variables shouldn't exist" is a bit strong. But if/when you use them, its super-important to make sure that they get deallocated corectly, so a disciplined naming convention for member versus local variables assists immeasurably with ensuring this.
  • josesuero
    josesuero almost 15 years
    Ah, I see. As far as I know, depositBankAccount is camel-case, and I think the most common name for DepositBankAccount is Pascal-case? (I never used Pascal, but I've heard this described as Pascal-case fairly often.)
  • Admin
    Admin almost 15 years
    @jalf I first learned Pascal in 1980, and back then people used a mishmash of ways of naming things. Borland's Delphi (probably the only Pascal survivor) uses the DepositBankAccount style, but so does what must be the most influential tech of them all - the Windows API.
  • mmmmmmmm
    mmmmmmmm almost 15 years
    @neil: I don't know exactly and simply thought both "depositBankAccount" and "DepositBankAccount" were camel case. Let's take a look what wikipedia says... Hey! They say the same! But is Wikipedia a authoritative source for this?
  • VoidPointer
    VoidPointer almost 15 years
    I mean to have read that the problem with Hungarien Notation just resulted from Simonyi being misunderstood. He wrote a prefix should be used to indicate the type of a variable where he meant "type" like in "kind of thing" not literal datatype. Later the platform guys at Microsoft picked it up and came up with lpsz... and the rest is history...
  • VoidPointer
    VoidPointer almost 15 years
    Prefixes that indicate type or kind of variable are also something worth a discussion, but I was referring mainly to prefixes indicating whether something is a (private) member/field. The reverse Hungarian notation you are mentioning can be quite handy when applied intelligently (like in your example). My favorite example where it makes sense is relative and absolute coordinates. when you see absX = relX you can plainly see that something might be wrong.you can also name functions accordingly: absX = absFromRel(relX, offset);
  • jkeys
    jkeys almost 15 years
    Please don't be making your member variables public. Just use accessors. The parentheses should tell the reader that it is a member variable.
  • mmmmmmmm
    mmmmmmmm almost 15 years
    @neil: I think there are far more naming conventions then there are names for. (I'm sure there are even people combining underscores with capital letters (Deposit_Bank_Account) and I'm sure there is no name for that :-)
  • Niels Dekker
    Niels Dekker almost 15 years
    Note: the initialization of aszFred is questionable (offering non-const access to a literal string), and the initialization of arrWilma won't even compile. (You probably intended to declare arrWilma as an array, instead of a pointer!) No problem though, as you wrote that it's just off the top of your head... :-)
  • ya23
    ya23 over 14 years
    Interesting. Looks a bit ugly at first, but I can see how it can be beneficial.
  • A. L. Flanagan
    A. L. Flanagan over 14 years
    Oops, you're absolutely right. Kids, don't try that at home. Do this: 'const char *aszFred = "Hi I'm a null-terminated string"; char arrWilma[] = {'O', 'o', 'p', 's'};'
  • Dan
    Dan over 14 years
    @rstevens: I thought This_Was_Called_Ada (Ada code is the only place I've seen that convention)
  • TonyK
    TonyK over 13 years
    These are not reserved words. They are reserved names. If they were reserved words, you couldn't use them at all. Because they are reserved names, you can use them, but at your own risk.
  • josesuero
    josesuero almost 13 years
    "s is for static" sounds pretty much like the "bad" form of Hungarian to me.
  • mbarnett
    mbarnett almost 13 years
    "So a class member with a leading underscore followed by a lower-case letter is legal, but sooner or late you're going to do the same to an identifier starting with upper-case, or otherwise break one of the above rules." -- class member variables aren't in the global namespace, so a leading underscore is safe, regardless of whether it's followed by a lower or uppercase letter.
  • josesuero
    josesuero almost 13 years
    @mbarnett: No, underscore followed by upper-case is reserved in general, not just in the global namespace.
  • Platinum Azure
    Platinum Azure over 12 years
    @MartinBeckett: You should capitalize the a in that scenario-- you're not doing it right otherwise. mApData (m prefix, then the variable name is apData).
  • Jason Williams
    Jason Williams over 12 years
    Then don't use it... Unless you think that your usage of the variable might be influenced by knowing that it is static...
  • user541686
    user541686 about 12 years
    The lps might be redundant, but the z isn't. It's certainly good to know whether a string is zero-terminated or not.
  • Jason Williams
    Jason Williams about 12 years
    @Mehrdad: I don't think z is very often useful in a language like C++ where that sort of low level implementation detail should be encapsulated in a class, but in C (where zero-termination is an important distinction) I agree with you. IMO any scheme we use should be adapted as required to best suit our own needs - So, if zero-termination affects your usage of the variable, there's nothing wrong with declaring "z" a useful prefix.
  • Thomas Eding
    Thomas Eding over 11 years
    The most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers. I whole heartedly disagree. If I use a pointer wrong, it simply won't compile (void* may be an exception for double pointers though). And the whole -> over . is enough to tell me it is a pointer. Also, if you are using autocomplete, your editor probably has declaration tooltips, eliminating the need for prefixing for variable information. Regardless, good answer.
  • Jason Williams
    Jason Williams over 11 years
    @Thomas: All good points. Some benefits are strong, some weaker. The stronger cases for p are for multiple indirections (X vs pX vs ppX) and pointer arithmetic (X++ vs pX++ vs *pX++), where knowing that something is a pointer is vital. For me, the other cases are still useful - compiling or tooltipping are IMO just less efficient ways of determining that a variable is a pointer (and the other cons: tooltips can't be copied and pasted into examples outside of your IDE, etc).
  • Admin
    Admin almost 11 years
    Upvoted for the clear, comprehensive and interesting explanations, however there is little here suggesting how this saves time in C++ YET remains largely unused in many other languages.
  • ulidtko
    ulidtko almost 10 years
    I'd also add n for 1-based numbers, counts and indexes. It's proven very useful to me. To be fair, indexes ought to be all 0-based (and have prefix i), but things happen. The n prefix helps to catch errors with index arithmetic. For example, int iLastItem = nDataItems - 1; should look fine to your internal typechecker, while m_TreeIndices[nLeftChild] = (iParent >= 1) ? iRightChild : null; should totally not.
  • Marson Mao
    Marson Mao almost 10 years
    surprised that this answer's vote is less than the prefix one.
  • Korchkidu
    Korchkidu over 9 years
    One of the nice point about auto is to not commit to some datatype. Weird that we would need to put this in the variable names now.
  • Jason Williams
    Jason Williams over 9 years
    @Korchkidu: auto/var can be useful where types are unknown, but most people use them to be lazy (avoid typing the big long type name) and this introduces exactly the "what type am I working with here?" problem that prefixes help to address. Hiding known types behind unnecessary autos is a very unhelpful practice as it obfuscates the code.
  • Korchkidu
    Korchkidu over 9 years
    @JasonWilliams: I have been refactoring code a lot those days. I wish I was using auto more. And not only for typing less. Auto forces you not to commit to some type. This is really helping in the long-run. IMHO of course. And not knowing which type your are working with is not a problem, it is a nice "feature" actually.
  • Reid Ellis
    Reid Ellis over 9 years
    In terms of naming, as soon as I see "numItems", I cringe. Variables should not be (implied) prepositional phrases ("number (of) items"). Rather, they should be nouns or noun phrases, e.g. "itemCount".
  • Jason Williams
    Jason Williams over 9 years
    That's a point of grammar which is correct but largely irrelevant in terms of "will people reading this code understand my intent?". I think numItems/itemCount are both fine, though generally readability flows from using a natural form, while yodaSpeak reduces it. (Aside: "count" isn't just a noun, it's also a verb. Consider .Net's IEnumerable.Count - does this return the "number of items" in a collection, or does it enumerate the collection and actually "count" how many items there are? This is a very important distinction which can be the cause of some horrific performance issues)
  • sydan
    sydan about 9 years
    I'd say it's a lot lot less ugly than:" mBar" or "m_bar".
  • avim
    avim about 9 years
    but then you have vector<int> v_; and writing v_.push_back(5) is pretty ugly too
  • Alexandru Irimiea
    Alexandru Irimiea over 8 years
    Is it recommended to use p prefix for smart pointers too? E.g.: std::unique_ptr<MyObject> pMyObject;
  • Jason Williams
    Jason Williams over 8 years
    It's up to you, but I'd say it's still a pointer so I'd use a "p" prefix for consistency... or if you feel it's important to differentiate smart pointers from regular ones, use a distinct prefix - e.b. you may prefer p for smart pointers and something like d for dangerous ones!)
  • Justme0
    Justme0 over 8 years
    That's Google C++ style.
  • underscore_d
    underscore_d over 8 years
    to be fair, you missed at least 2 other options, e.g. (a) use full names like foo only for members and instead use single-letter or short names for parameters or other locals/throwaways, such as int f; or (b) prefix the parameters or other locals with something. good point re m_ and pods, though; i've independently arrived at a preference to follow both of those guidelines, for the most part.
  • underscore_d
    underscore_d over 8 years
    "between things such as public and private members" - how common is this really? i don't recall seeing it, but then again, i don't go around reviewing codebases or anything.
  • Mr. Will
    Mr. Will over 8 years
    I don't do it in my own coding, but I've worked at places where we had to do it based on their code convention guides. I prefer to not do it as almost all IDEs will show private variables a different color.
  • underscore_d
    underscore_d over 8 years
    Hmm, I guess it only happens in different situations than mine. Normally I use either classes all of whose members are private/protected, or POD structs all of whose variables are public (and often also const). So, I never need to wonder about the access level of any given member.
  • DBedrenko
    DBedrenko about 8 years
    Thanks for the answer. I'm adopting your style. When multiple prefixes apply do you include all of them, e.g. mpsMyVar? I'm guessing in alphabetical order?
  • Jason Williams
    Jason Williams about 8 years
    @SpaghettiCat: Good question. For C++, yes (e.g. 'p' is a local pointer, 'mp' is a member pointer, so there is a significant difference). In C# a const or static implies that it's a member, so I just use 'm', 'c' or 's' on their own. So I adjust the scheme to best fit each language I use it in. Order them however you prefer, just try to be consistent,
  • DBedrenko
    DBedrenko about 8 years
    I was thinking that applying this convention to public members is not good, because it makes the API provided to others look less clean. Not everyone will understand the convention and it has the potential to confuse. So I'll following the Android variation where public members aren't prefixed with "m" (... I'm not sure whether I should also not apply the other prefixes...)
  • Jason Williams
    Jason Williams about 8 years
    @SpaghettiCat: This description is based on the assumption that classes use encapsulation, i.e. that member variables are never public. To expose a member variable to external callers, we would provide an accessor or property (to which the member variable prefixing scheme would not normally be applied).
  • Guney Ozsan
    Guney Ozsan about 8 years
    This is the most intuitive solution with the fastest learning curve I've ever heard. I wish spoken languages were more flexible to handle all those so that we didn't have to think about coming up with new techniques to solve ambiguities in code.
  • Terrabits
    Terrabits almost 8 years
    This is the reason I prefix. I think foo.name() is much more readable than foo.get_name() in my opinion.
  • sourcedelica
    sourcedelica over 7 years
    After working with C++ for a little bit I can see one reason why prefixing is more popular in that language. It's because member variables and member functions share the same namespace, unlike Java and more modern languages. You run out of names faster. It's pretty annoying actually.
  • David
    David over 7 years
    I agree with this answer, just use this-> if you need to specify that its a member variable, or don't, that's good too.
  • Caduchon
    Caduchon over 6 years
    Note that there is a warning in gcc (>= 4.6) to detect clash of names : -Wshadow
  • Caduchon
    Caduchon over 6 years
    Moreover, you don't have to document your convention to give your code to other people. Everyone understand what this-> means.
  • Ruslan
    Ruslan over 6 years
    Double underscore is reserved in any position, not only at the beginning of the name.
  • Sascha
    Sascha over 6 years
    To support this: C++ Core Guidelines don't use prefixes in their examples either: isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
  • user924
    user924 about 6 years
    for constants it's better to use without prefix but all letters are uppercase - CONSTANT_VARIABLE
  • Jason Williams
    Jason Williams about 6 years
    @user924: All-caps/underscores were historically popular so you'll see them used a lot, but are no longer considered "best practice". They make code (and documentation) less readable, and many environments (C, C++, C#, VB, Java) assign special meaning to underscores. Using a prefixing scheme is more consistent and means less work when refactoring a member between being a constant, a property or variable. It also allows you to differentiate constant, readonly, & macro. You can use whatever scheme you wish: I'd just encourage you to think about the reason for preferring that scheme.
  • Toast
    Toast about 5 years
    You could also type this->
  • Chris Olsen
    Chris Olsen about 4 years
    Thanks for the s_ idea. Seems very useful, and somehow had never occurred to me.
  • Oleksa
    Oleksa almost 4 years
    @jalf: Why do you think "s for static" is bad?
  • antho
    antho over 3 years
    @Jason Williams: What do you use for a C array? mArray, pArray or something else?
  • Jason Williams
    Jason Williams over 3 years
    @antho: I tend to use a suffix for lists (of any form, i.e. arrays, list collections, linked lists - so an array of vehicles would be a "vehicleList"). Any prefix should clarify the usage of the array ("m" for member etc). Consider: Giving every string a "p" prefix just because it's technically a "pointer to an array of char" wouldn't typically add value (we don't usually need to "use" strings as arrays), so I usually wouldn't use a prefix, but if I were using a pointer-to-char to step through the characters within a string, I would absolutely use a "p" prefix to clarify this.
  • antho
    antho over 3 years
    Ok thanks, the combination of sufix and prefix might be good. Thanks for your advice
  • Cuadrix
    Cuadrix over 3 years
    I don't like this coding style at all. Suffixes are all subjective and might refer to any type of variable depending on the coder (like you just demonstrated), while a simple use of "this->" is clear and unambiguous. Not to mention that this suffix style just brings noise to code bases that prefer the usage of "snake_case" for consistency with the standard library. That being said, I'd rather avoid suffixes.
  • Dan Bechard
    Dan Bechard over 3 years
    @underscore_d Parameter names are part of the public interface of a class. That should be the last place you're adding weird naming conventions. Also, single letter variable names are awful and should be avoided at all costs with very few exceptions (i in a loop).
  • Traummaennlein
    Traummaennlein about 2 years
    But that's more typing ;-)