181

A lot of C++ code uses syntactical conventions for marking up data members. 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 data member 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 data members.

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?

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
VoidPointer
  • 17,651
  • 15
  • 54
  • 58
  • 21
    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) – Joe Aug 04 '09 at 15:35
  • 6
    You've never seen it in Ruby because of @ for attribute, and the idiom of generating accessors in preference to using attributes directly. – Steve Jessop Aug 04 '09 at 17:17
  • 7
    According to [PEP 8](http://www.python.org/dev/peps/pep-0008/) non-public member variables are to be prefixed with an underscore in Python (example: `self._something = 1`). – Nathan Osman Apr 02 '13 at 01:52
  • 2
    Shouldn't editor's syntax highlighting be used to identify these? – too Jul 14 '15 at 14:49
  • 4
    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. – matec May 14 '16 at 08:23
  • 1
    This may be interesting for you: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#nl5-avoid-encoding-type-information-in-names – Kostiantyn Ponomarenko Jun 18 '18 at 07:56
  • 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::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. https://stackoverflow.com/a/24368629/4276112 – mosegui Oct 14 '21 at 11:45
  • _"Shouldn't editor's syntax highlighting be used to identify these?"_ Of course, they should. But the depressingly common general attitude that _"your IDE will do it for you, so you shouldn't care"_ is fundamentally equivalent to "advices" like _"Don't learn how to write, use your phone, duh!"_... We do of course delegate much of human civilization (knowledge, culture) to _things_, but we can _never_ fully eliminate situations when (some of) those things get (routinely) change in problematic ways, or even suddenly disappear. And then it's all about _our own_ ability to cope/recover. – Sz. Feb 11 '23 at 14:17

31 Answers31

274

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.

Jason Williams
  • 56,972
  • 11
  • 108
  • 137
  • 8
    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 Aug 04 '09 at 23:04
  • 24
    "s is for static" sounds pretty much like the "bad" form of Hungarian to me. – jalf Aug 24 '11 at 11:46
  • 1
    Then don't use it... Unless you think that your _usage_ of the variable might be influenced by knowing that it is static... – Jason Williams Dec 06 '11 at 09:02
  • 4
    The `lps` might be redundant, but the `z` isn't. It's certainly good to know whether a string is zero-terminated or not. – user541686 Apr 22 '12 at 22:39
  • 7
    @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. – Jason Williams Apr 23 '12 at 19:06
  • 19
    `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. – Thomas Eding Nov 14 '12 at 07:27
  • 1
    @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). – Jason Williams Nov 14 '12 at 09:20
  • 7
    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. –  Jun 21 '13 at 17:16
  • 2
    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. – ulidtko Aug 08 '14 at 19:09
  • 1
    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. – Korchkidu Jan 09 '15 at 11:01
  • @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. – Jason Williams Jan 09 '15 at 16:49
  • 3
    @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. – Korchkidu Jan 10 '15 at 11:51
  • 2
    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". – Reid Ellis Feb 19 '15 at 02:13
  • 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) – Jason Williams Feb 19 '15 at 12:20
  • Is it recommended to use `p` prefix for smart pointers too? E.g.: `std::unique_ptr pMyObject;` – Alexandru Irimiea Oct 03 '15 at 13:57
  • 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!) – Jason Williams Oct 05 '15 at 19:05
  • 2
    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? – DBedrenko Mar 28 '16 at 14:07
  • 2
    @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, – Jason Williams Mar 28 '16 at 22:08
  • 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](http://source.android.com/source/code-style.html#follow-field-naming-conventions) where public members aren't prefixed with "m" (... I'm not sure whether I should also not apply the other prefixes...) – DBedrenko May 04 '16 at 08:04
  • 1
    @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). – Jason Williams May 04 '16 at 20:50
  • 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. – sourcedelica Dec 09 '16 at 01:58
  • for constants it's better to use without prefix but all letters are uppercase - CONSTANT_VARIABLE – user924 Mar 19 '18 at 10:35
  • @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. – Jason Williams Mar 20 '18 at 22:54
  • @jalf: Why do you think "s for static" is bad? – Oleksa Jun 26 '20 at 07:52
  • @Jason Williams: What do you use for a C array? mArray, pArray or something else? – antho Oct 22 '20 at 19:05
  • @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. – Jason Williams Oct 25 '20 at 22:00
  • Ok thanks, the combination of sufix and prefix might be good. Thanks for your advice – antho Oct 26 '20 at 18:39
  • 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. – Cuadrix Dec 24 '20 at 23:53
  • It interesting that you think the bad Hungarian notation is encoding data type into the variable name (as a prefix), but then you suggest encoding (partial) data type into the name. `pointer` is a type. Also what happens if you have a const pointer to a variable or a pointer to a const variable or a const pointer to a const variable do you write cpc prefix? A read-only HW register is represented as a pointer to a const volatile memory address, do you encode this into the variable name? 'size' could be const or not (maybe template) does it matter? If changed do you have to rewrite your code? – Steven Spark May 11 '23 at 18:00
  • @StevenSpark: The aim is to illuminate important details of the _usage_ rather than just regurgitating the _type_. If it is useful to you to know that something is a const pointer, then yes, that information can be included in the prefix. Following the scheme presented here a const pointer to a volatile would be "pv" or "cpv" - whichever form is most _useful_ to you. – Jason Williams May 13 '23 at 22:12
  • @StevenSpark: If you change the _usage_ of a variable (e.g. make a value constant or volatile, or change a list to a dictionary) then, yes, you should update the variable name and/or prefix so that it is a _meaningful description of its purpose_ to help out the next programmer who has to read your code. – Jason Williams May 13 '23 at 22:17
  • @JasonWilliams I agree that usage is what matters. If the name helps you use it correctly that’s a good way to name things. For example sanitized and unsafe (user input) strings can be the same type (char*/string) but they shouldn’t be mixed. The same way you don’t add kg to km even if they are both float... and/or member, static, const, volatile… Name should reflect what they are not what data type they are. That’s the real Hungarian notation. – Steven Spark Jul 18 '23 at 22:15
  • @JasonWilliams m,s: Maybe we are working on different kind of things, but usually I don’t really care where a variable is located (member, local, static) and when I do the IDE colors them differently anyway. When using (reading) them it doesn’t matter if it’s a member or a local cached copy, is it? Only if you write to them is when it matters, right? I’d rather use a _ suffix for members if I just want to differentiate/avoid name conflict, or name function arguments differently (an ‘a’ prefix maybe). Or when and why is it important if something is a member or not? – Steven Spark Jul 18 '23 at 22:42
  • @JasonWilliams v: When I want to calculate something it doesn’t really matter if one of the parameters is constant or not, or volatile or not. Obviously it matters when waiting on flags set by IRQ handlers or other cases involving concurrency. But HW registers are always volatile and I have never seen any library prefixing them with v;) When do you find useful marking names with volatile? – Steven Spark Jul 18 '23 at 22:54
  • @JasonWilliams c: You can add a constant offset to a measured value (of the same kind/type), or the correction could be a run time calculated value. Changing from one to the other shouldn’t change the equation, shouldn’t require a rewrite, generate extra noise in version control (“What did they modify in this equation? Oh, a variable name. Great!”) I don’t think something being constant has anything to do with “meaningful description of its purpose”. Being const is not its purpose but a circumstance. Not being able to change windows background color is not its purpose but lazy implementation:) – Steven Spark Jul 18 '23 at 22:56
  • @JasonWilliams p: I agree that differentiating between pointers and values is useful... but C string are also pointers and it would feel weird starting them with p. I’d rather start them with s or str, but most of the time with nothing (like name, host, path … it’s pretty clear they are strings and not float or int...). (I don’t use std::string on embedded, then I would use str for those.) Arrays can also decay to pointers, but I wouldn’t use p prefix for arrays, use good wrappers instead. When I can I use references instead of pointers anyways. For low level stuff, sure use pDst++=pSrc++ ;) – Steven Spark Jul 18 '23 at 23:23
  • @JasonWilliams i: For array indexing I usually use idx prefix if more then one index is nearby (but i is fine too). If there is only one loop variable in sight then a simple idx or even just i is enough. (Being more specific is good in case the code could be moved near another loop.) An index is an index and not mass, distance... it can be int, uint8..64, rarely matters. Could be volatile... or even const. This is the first that I think we fully agree on. Because this and events are the first and only 2 which are conceptually differentiated and not by the type system. – Steven Spark Jul 18 '23 at 23:26
  • @JasonWilliams e: I like e for exceptions, but since I mostly work on micro-controllers with exceptions disabled it doesn’t really come up (neither do events). Enums come up more frequently but I don’t prefix them with e. I like the Delphi, C# event system. What do you use for C++? – Steven Spark Jul 18 '23 at 23:45
135

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.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • "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. –  Sep 08 '11 at 06:22
  • 3
    @mbarnett: No, underscore followed by upper-case is reserved *in general*, not just in the global namespace. – jalf Sep 08 '11 at 07:45
  • 10
    surprised that this answer's vote is less than the prefix one. – Marson Mao Sep 02 '14 at 08:47
  • 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. – David Jan 10 '17 at 22:14
  • Moreover, you don't have to document your convention to give your code to other people. Everyone understand what `this->` means. – Caduchon Sep 21 '17 at 08:41
  • Double underscore is reserved in any position, not only at the beginning of the name. – Ruslan Sep 21 '17 at 14:54
  • To support this: C++ Core Guidelines don't use prefixes in their examples either: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines – Sascha Nov 07 '17 at 09:59
  • I kinda like this, but downsides of the _occasional_ `this->`: a) casual readers may not immediately know _a priori_ that a usage is ambiguous -- they have to understand first what they're seeing, and it'll always leave a bit of uncertainty for the cases where it's not there. b) It's impossible to make it a low-level automatic brain function of a habit: its conditional nature will always require a bit more processing than a "regular" convention (which exist exactly for this reason: to eliminate thinking). (And of course the all-in `this->` convention is just too tedious.) – Sz. Feb 11 '23 at 14:58
  • "you can't see at a glance whether a variable is a class member or not" ... yes you can if you use the right editor/IDE. Eclipse CDT colors those differently ! ;) I feel like this is another convention from before modern editors. – Steven Spark May 11 '23 at 18:16
  • In my mind I arrange constructs based on what they refer to (a name, string, index, capacity, time, weight, UART, LED, valve...) and not where they are declared. It's much easier to start typing a variable name if you know what you want to access (an index or size of a buffer) rather that thinking about where was it declared (index can be local while size member). So I don't use prefixes. (I might use suffixes to note measurement units like ms, us, s, clk...) But maybe your mind works differently, and organizes stuff along other lines and other naming schemes work better for you. – Steven Spark May 11 '23 at 18:21
55

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?

Community
  • 1
  • 1
Juan
  • 3,667
  • 3
  • 28
  • 32
  • 6
    Actually, both _foo and _l are reserved at namespace scope. –  Aug 04 '09 at 15:36
  • 13
    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. – Juan Aug 04 '09 at 15:40
  • 13
    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. – TonyK Nov 30 '10 at 21:27
34

I prefer postfix underscores, like such:

class Foo
{
   private:
      int bar_;

   public:
      int bar() { return bar_; }
};
jkeys
  • 3,803
  • 11
  • 39
  • 63
24

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..

Grumbel
  • 6,585
  • 6
  • 39
  • 50
  • 2
    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 Jan 28 '16 at 01:08
  • 3
    @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). – Dan Bechard Feb 13 '21 at 09:47
  • @DanBechard Good point about param names in APIs, but the name conflicts we're discussing don't happen there, they happen in the _implementation_. And there you're free to have some cosmetic deviations from the interface. (Of course, that would require some extra effort for something that's not even good practice, just the ifc/docs argument doesn't hold is all I'm saying.) One-letter vars have their legit roles, they can even help reducing noise and clutter, esp. in small/straightforward sections. _Orthodoxy_ is considered more harmful in my book than those. – Sz. Feb 12 '23 at 23:51
  • "longer to type" is a non-argument; remember that "code is read much more than it is written" - so readability trumps everything else. Also, re. "documentation" is non-argument too (at least for 2 reasons; first, IF it is such a huge concern - nobody has said that declaration == definition; second, if "documentation" is meant as doxygen - the only use for it I've seen in my 30+ years - including 20+ at architect positions, is to make managers happy, so its quality doesn't matter at all). – No-Bugs Hare May 13 '23 at 18:10
14

When reading through a member function, knowing who "owns" each variable is absolutely essential to understanding the meaning of the variable. In a function like this:

void Foo::bar( int apples )
{
    int bananas = apples + grapes;
    melons = grapes * bananas;
    spuds += melons;
}

...it's easy enough to see where apples and bananas are coming from, but what about grapes, melons, and spuds? Should we look in the global namespace? In the class declaration? Is the variable a member of this object or a member of this object's class? Without knowing the answer to these questions, you can't understand the code. And in a longer function, even the declarations of local variables like apples and bananas can get lost in the shuffle.

Prepending a consistent label for globals, member variables, and static member variables (perhaps g_, m_, and s_ respectively) instantly clarifies the situation.

void Foo::bar( int apples )
{
    int bananas = apples + g_grapes;
    m_melons = g_grapes * bananas;
    s_spuds += m_melons;
}

These may take some getting used to at first—but then, what in programming doesn't? There was a day when even { and } looked weird to you. And once you get used to them, they help you understand the code much more quickly.

(Using "this->" in place of m_ makes sense, but is even more long-winded and visually disruptive. I don't see it as a good alternative for marking up all uses of member variables.)

A possible objection to the above argument would be to extend the argument to types. It might also be true that knowing the type of a variable "is absolutely essential to understanding the meaning of the variable." If that is so, why not add a prefix to each variable name that identifies its type? With that logic, you end up with Hungarian notation. But many people find Hungarian notation laborious, ugly, and unhelpful.

void Foo::bar( int iApples )
{
    int iBananas = iApples + g_fGrapes;
    m_fMelons = g_fGrapes * iBananas;
    s_dSpuds += m_fMelons;
}

Hungarian does tell us something new about the code. We now understand that there are several implicit casts in the Foo::bar() function. The problem with the code now is that the value of the information added by Hungarian prefixes is small relative to the visual cost. The C++ type system includes many features to help types either work well together or to raise a compiler warning or error. The compiler helps us deal with types—we don't need notation to do so. We can infer easily enough that the variables in Foo::bar() are probably numeric, and if that's all we know, that's good enough for gaining a general understanding of the function. Therefore the value of knowing the precise type of each variable is relatively low. Yet the ugliness of a variable like "s_dSpuds" (or even just "dSpuds") is great. So, a cost-benefit analysis rejects Hungarian notation, whereas the benefit of g_, s_, and m_ overwhelms the cost in the eyes of many programmers.

OldPeculier
  • 11,049
  • 13
  • 50
  • 76
10

I can't say how widespred it is, but speaking personally, I always (and have always) prefixed my member variables with 'm'. E.g.:

class Person {
   .... 
   private:
       std::string mName;
};

It's the only form of prefixing I do use (I'm very anti Hungarian notation) but it has stood me in good stead over the years. As an aside, I generally detest the use of underscores in names (or anywhere else for that matter), but do make an exception for preprocessor macro names, as they are usually all uppercase.

  • 5
    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. – Martin Beckett Aug 04 '09 at 15:44
  • I have a cunning plan for dealing with that - I don't use camel case. –  Aug 04 '09 at 15:48
  • 1
    @Neil I am with you. @mgb: I hate names starting with '_' It is just an invitation for things to go wrong in the future. – Martin York Aug 04 '09 at 16:20
  • 1
    @Neil: Which convention do you use then, if you don't use underscores, and don't use camelcase? – jalf Aug 04 '09 at 17:07
  • @jalf Class names & member variables per the example above. Functions as for class names. Local variables & params all lowercase, with short names –  Aug 04 '09 at 17:10
  • @jalf and I should have said multi word class/function names like this: DepositBankAccount. –  Aug 04 '09 at 17:12
  • @neil: What is "DepositBankAccount" if it isn't camel case? – mmmmmmmm Aug 04 '09 at 19:18
  • 1
    I thoght camel case was "depositBankAccount". Or am I getting confused? –  Aug 04 '09 at 19:25
  • 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.) – jalf Aug 04 '09 at 20:13
  • @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. –  Aug 04 '09 at 20:19
  • @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? – mmmmmmmm Aug 04 '09 at 22:24
  • @rstevens Is it the authoritative source on anything? Can a man step into the same river once? To be honest, "camel case" is a term I don't believe I have ever typed before this thread. I only used it because mgb did in his comment. –  Aug 04 '09 at 22:51
  • @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 :-) – mmmmmmmm Aug 05 '09 at 07:18
  • 2
    My understanding was that it is camelCase which makes using just m for variables like 'apData' confusing - it becomes 'mapData' rather than 'm_apData'. I use _camelCase for protected/private member variables because it stands out – Martin Beckett Sep 04 '09 at 21:16
  • @rstevens: I thought This_Was_Called_Ada (Ada code is the only place I've seen that convention) – Dan Mar 03 '10 at 18:01
  • 11
    @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`). – Platinum Azure Oct 21 '11 at 18:27
10

The main reason for a member prefix is to distinguish between a member function and a member variable with the same name. This is useful if you use getters with the name of the thing.

Consider:

class person
{
public:
    person(const std::string& full_name)
        : full_name_(full_name)
    {}

    const std::string& full_name() const { return full_name_; }
private:
    std::string full_name_;
};

The member variable could not be named full_name in this case. You need to rename the member function to get_full_name() or decorate the member variable somehow.

Wolf
  • 9,679
  • 7
  • 62
  • 108
  • 2
    This is the reason I prefix. I think `foo.name()` is much more readable than `foo.get_name()` in my opinion. – Terrabits Jul 14 '16 at 16:49
  • 1
    @Wolf what do you mean by a member function *local*? I think the OP's original intention is just distinguishing a member function's name, isn't it? – starriet Jul 28 '22 at 23:42
  • 1
    @Wolf This answer (and also the code) is talking about the member function's name, not the member function's local variables' name. The local variables of the member function `full_name()` don't even exist in this code example. (BTW, I meant 'answerer' when I said 'OP' in my previous comment) – starriet Aug 01 '22 at 01:16
  • 1
    @starriet: I now rolled back [my first edit](https://stackoverflow.com/revisions/1231144/2). To explain my misunderstanding: I never focus on getters and setters in C++. So thanks for your intransigence on this point. – Wolf Aug 01 '22 at 07:42
6

I don't think one syntax has real value over another. It all boils down, like you mentionned, to uniformity across the source files.

The only point where I find such rules interesting is when I need 2 things named identicaly, for example :

void myFunc(int index){
  this->index = index;
}

void myFunc(int index){
  m_index = index;
}

I use it to differentiate the two. Also when I wrap calls, like from windows Dll, RecvPacket(...) from the Dll might be wrapped in RecvPacket(...) in my code. In these particular occasions using a prefix like "_" might make the two look alike, easy to identify which is which, but different for the compiler

Eric
  • 19,525
  • 19
  • 84
  • 147
6

Some responses focus on refactoring, rather than naming conventions, as the way to improve readability. I don't feel that one can replace the other.

I've known programmers who are uncomfortable with using local declarations; they prefer to place all the declarations at the top of a block (as in C), so they know where to find them. I've found that, where scoping allows for it, declaring variables where they're first used decreases the time that I spend glancing backwards to find the declarations. (This is true for me even for small functions.) That makes it easier for me to understand the code I'm looking at.

I hope it's clear enough how this relates to member naming conventions: When members are uniformly prefixed, I never have to look back at all; I know the declaration won't even be found in the source file.

I'm sure that I didn't start out preferring these styles. Yet over time, working in environments where they were used consistently, I optimized my thinking to take advantage of them. I think it's possible that many folks who currently feel uncomfortable with them would also come to prefer them, given consistent usage.

Dan Breslau
  • 11,472
  • 2
  • 35
  • 44
5

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

That is usually because there is no prefix. The compiler needs enough information to resolve the variable in question, be it a unique name because of the prefix, or via the this keyword.

So, yes, I think prefixes are still useful. I, for one, would prefer to type '_' to access a member rather than 'this->'.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 3
    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 – rmeador Aug 04 '09 at 15:37
  • 2
    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. – Kent Boogaart Aug 04 '09 at 15:44
  • 1
    Exactly why I use 'm_'. I don't like locals with the same name as my member vars. – Ed S. Aug 04 '09 at 17:04
  • 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. – jalf Aug 04 '09 at 17:08
  • 6
    Why is that a code smell? I'd say it's perfectly common and reasonable, especially when it comes to constructors. – Kent Boogaart Aug 04 '09 at 17:19
  • @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? – Ed S. Aug 04 '09 at 17:20
  • 3
    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) { ... } };` – Pavel Minaev Aug 04 '09 at 17:33
  • 3
    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) {...}` – Steve Jessop Aug 04 '09 at 17:40
  • @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. – mmmmmmmm Aug 04 '09 at 19:23
5

Those conventions are just that. Most shops use code conventions to ease code readability so anyone can easily look at a piece of code and quickly decipher between things such as public and private members.

Mr. Will
  • 2,298
  • 3
  • 21
  • 27
  • "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. – underscore_d Jan 28 '16 at 01:10
  • 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. – Mr. Will Jan 28 '16 at 02:42
  • Hmm, I guess it only happens in different situations than mine. Normally I use either `class`es all of whose members are `private`/`protected`, or POD `struct`s all of whose variables are `public` (and often also `const`). So, I never need to wonder about the access level of any given member. – underscore_d Jan 28 '16 at 10:36
4

Other languages will use coding conventions, they just tend to be different. C# for example has probably two different styles that people tend to use, either one of the C++ methods (_variable, mVariable or other prefix such as Hungarian notation), or what I refer to as the StyleCop method.

private int privateMember;
public int PublicMember;

public int Function(int parameter)
{
  // StyleCop enforces using this. for class members.
  this.privateMember = parameter;
}

In the end, it becomes what people know, and what looks best. I personally think code is more readable without Hungarian notation, but it can become easier to find a variable with intellisense for example if the Hungarian notation is attached.

In my example above, you don't need an m prefix for member variables because prefixing your usage with this. indicates the same thing in a compiler-enforced method.

This doesn't necessarily mean the other methods are bad, people stick to what works.

Will Eddins
  • 13,628
  • 5
  • 51
  • 85
3

When you have a big method or code blocks, it's convenient to know immediately if you use a local variable or a member. it's to avoid errors and for better clearness !

Matthieu
  • 2,743
  • 19
  • 21
  • 3
    If you have a big method, for better clearness break it down. – sbi Aug 04 '09 at 15:52
  • 4
    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). – Steve Broberg Aug 04 '09 at 17:12
  • 3
    @sbi: Guidelines are just that; guidelines, not rules. Sometimes you need large methods that don't logically lend themselves to being split apart, and sometimes parameter names clash with members. – Ed S. Aug 04 '09 at 17:23
  • Please don't be making your member variables public. Just use accessors. The parentheses should tell the reader that it is a member variable. – jkeys Aug 05 '09 at 00:34
  • Note that there is a warning in gcc (>= 4.6) to detect clash of names : `-Wshadow` – Caduchon Sep 21 '17 at 08:27
3

IMO, this is personal. I'm not putting any prefixes at all. Anyway, if code is meaned to be public, I think it should better has some prefixes, so it can be more readable.

Often large companies are using it's own so called 'developer rules'.
Btw, the funniest yet smartest i saw was DRY KISS (Dont Repeat Yourself. Keep It Simple, Stupid). :-)

Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95
3

As others have already said, the importance is to be colloquial (adapt naming styles and conventions to the code base in which you're writing) and to be consistent.

For years I have worked on a large code base that uses both the "this->" convention as well as using a postfix underscore notation for member variables. Throughout the years I've also worked on smaller projects, some of which did not have any sort of convention for naming member variables, and other which had differing conventions for naming member variables. Of those smaller projects, I've consistently found those which lacked any convention to be the most difficult to jump into quickly and understand.

I'm very anal-retentive about naming. I will agonize over the name to be ascribed to a class or variable to the point that, if I cannot come up with something that I feel is "good", I will choose to name it something nonsensical and provide a comment describing what it really is. That way, at least the name means exactly what I intend it to mean--nothing more and nothing less. And often, after using it for a little while, I discover what the name should really be and can go back and modify or refactor appropriately.

One last point on the topic of an IDE doing the work--that's all nice and good, but IDEs are often not available in environments where I have perform the most urgent work. Sometimes the only thing available at that point is a copy of 'vi'. Also, I've seen many cases where IDE code completion has propagated stupidity such as incorrect spelling in names. Thus, I prefer to not have to rely on an IDE crutch.

Chris Cleeland
  • 4,760
  • 3
  • 26
  • 28
3

The original idea for prefixes on C++ member variables was to store additional type information that the compiler didn't know about. So for example, you could have a string that's a fixed length of chars, and another that's variable and terminated by a '\0'. To the compiler they're both char *, but if you try to copy from one to the other you get in huge trouble. So, off the top of my head,

char *aszFred = "Hi I'm a null-terminated string";
char *arrWilma = {'O', 'o', 'p', 's'};

where "asz" means this variable is "ascii string (zero-terminated) and "arr" means this variable is a character array.

Then the magic happens. The compiler will be perfectly happy with this statement:

strcpy(arrWilma, aszFred);

But you, as a human, can look at it and say "hey, those variables aren't really the same type, I can't do that".

Unfortunately a lot places use standards such as "m_" for member variables, "i" for integers no matter how used, "cp" for char pointers. In other words they're duplicating what the compiler knows, and making the code hard to read at the same time. I believe this pernicious practice should be outlawed by statute and subject to harsh penalties.

Finally, there's two points I should mention:

  • Judicious use of C++ features allows the compiler to know the information you had to encode in raw C-style variables. You can make classes that will only allow valid operations. This should be done as much as practical.
  • If your code blocks are so long that you forget what type a variable is before you use it, they are way too long. Don't use names, re-organize.
A. L. Flanagan
  • 1,162
  • 8
  • 22
  • 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); – VoidPointer Aug 04 '09 at 23:10
  • 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... :-) – Niels Dekker Aug 07 '09 at 13:48
  • 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'};' – A. L. Flanagan Dec 31 '09 at 21:11
3

Our project has always used "its" as a prefix for member data, and "the" as a prefix for parameters, with no prefix for locals. It's a little cutesy, but it was adopted by the early developers of our system because they saw it used as a convention by some commercial source libraries we were using at the time (either XVT or RogueWave - maybe both). So you'd get something like this:

void
MyClass::SetName(const RWCString &theName)
{
   itsName = theName;
}

The big reason I see for scoping prefixes (and no others - I hate Hungarian notation) is that it prevents you from getting into trouble by writing code where you think you're referring to one variable, but you're really referring to another variable with the same name defined in the local scope. It also avoids the problem of coming up with a variable names to represent that same concept, but with different scopes, like the example above. In that case, you would have to come up with some prefix or different name for the parameter "theName" anyway - why not make a consistent rule that applies everywhere.

Just using this-> isn't really good enough - we're not as interested in reducing ambiguity as we are in reducing coding errors, and masking names with locally scoped identifiers can be a pain. Granted, some compilers may have the option to raise warnings for cases where you've masked the name in a larger scope, but those warnings may become a nuisance if you're working with a large set of third party libraries that happen to have chosen names for unused variables that occasionally collide with your own.

As for the its/the itself - I honestly find it easier to type than underscores (as a touch typist, I avoid underscores whenever possible - too much stretching off the home rows), and I find it more readable than a mysterious underscore.

Steve Broberg
  • 4,255
  • 3
  • 28
  • 40
  • 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. – Guney Ozsan Jun 05 '16 at 13:07
2

I think that, if you need prefixes to distinguish class members from member function parameters and local variables, either the function is too big or the variables are badly named. If it doesn't fit on the screen so you can easily see what is what, refactor.

Given that they often are declared far from where they are used, I find that naming conventions for global constants (and global variables, although IMO there's rarely ever a need to use those) make sense. But otherwise, I don't see much need.

That said, I used to put an underscore at the end of all private class members. Since all my data is private, this implies members have a trailing underscore. I usually don't do this anymore in new code bases, but since, as a programmer, you mostly work with old code, I still do this a lot. I'm not sure whether my tolerance for this habit comes from the fact that I used to do this always and am still doing it regularly or whether it really makes more sense than the marking of member variables.

sbi
  • 219,715
  • 46
  • 258
  • 445
  • 2
    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. – VoidPointer Aug 04 '09 at 15:55
2

I use it because VC++'s Intellisense can't tell when to show private members when accessing out of the class. The only indication is a little "lock" symbol on the field icon in the Intellisense list. It just makes it easier to identify private members(fields) easier. Also a habit from C# to be honest.

class Person {
   std::string m_Name;
public:
   std::string Name() { return m_Name; }
   void SetName(std::string name) { m_Name = name; }
};

int main() {
  Person *p = new Person();
  p->Name(); // valid
  p->m_Name; // invalid, compiler throws error. but intellisense doesn't know this..
  return 1;
}
Zack
  • 2,477
  • 4
  • 37
  • 50
2

In python leading double underscores are used to emulate private members. For more details see this answer

Community
  • 1
  • 1
Konstantin Tenzin
  • 12,398
  • 3
  • 22
  • 20
2

I use m_ for member variables just to take advantage of Intellisense and related IDE-functionality. When I'm coding the implementation of a class I can type m_ and see the combobox with all m_ members grouped together.

But I could live without m_ 's without problem, of course. It's just my style of work.

Hernán
  • 4,527
  • 2
  • 32
  • 47
1

It is useful to differentiate between member variables and local variables due to memory management. Broadly speaking, heap-allocated member variables should be destroyed in the destructor, while heap-allocated local variables should be destroyed within that scope. Applying a naming convention to member variables facilitates correct memory management.

frankster
  • 1,529
  • 2
  • 16
  • 20
  • 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. – jalf Aug 04 '09 at 17:02
  • "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. – frankster Aug 04 '09 at 19:30
1

Code Complete recommends m_varname for member variables.

While I've never thought the m_ notation useful, I would give McConnell's opinion weight in building a standard.

Paul Nathan
  • 39,638
  • 28
  • 112
  • 212
  • 2
    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). –  Aug 04 '09 at 18:09
1

I almost never use prefixes in front of my variable names. If you're using a decent enough IDE you should be able to refactor and find references easily. I use very clear names and am not afraid of having long variable names. I've never had trouble with scope either with this philosophy.

The only time I use a prefix would be on the signature line. I'll prefix parameters to a method with _ so I can program defensively around them.

James
  • 6,471
  • 11
  • 59
  • 86
1

You should never need such a prefix. If such a prefix offers you any advantage, your coding style in general needs fixing, and it's not the prefix that's keeping your code from being clear. Typical bad variable names include "other" or "2". You do not fix that with requiring it to be mOther, you fix it by getting the developer to think about what that variable is doing there in the context of that function. Perhaps he meant remoteSide, or newValue, or secondTestListener or something in that scope.

It's an effective anachronism that's still propagated too far. Stop prefixing your variables and give them proper names whose clarity reflects how long they're used. Up to 5 lines you could call it "i" without confusion; beyond 50 lines you need a pretty long name.

dascandy
  • 7,184
  • 1
  • 29
  • 50
1

I like variable names to give only a meaning to the values they contain, and leave how they are declared/implemented out of the name. I want to know what the value means, period. Maybe I've done more than an average amount of refactoring, but I find that embedding how something is implemented in the name makes refactoring more tedious than it needs to be. Prefixes indicating where or how object members are declared are implementation specific.

color = Red;

Most of the time, I don't care if Red is an enum, a struct, or whatever, and if the function is so large that I can't remember if color was declared locally or is a member, it's probably time to break the function into smaller logical units.

If your cyclomatic complexity is so great that you can't keep track of what is going on in the code without implementation-specific clues embedded in the names of things, most likely you need to reduce the complexity of your function/method.

Mostly, I only use 'this' in constructors and initializers.

hata
  • 11,633
  • 6
  • 46
  • 69
ChrisG65
  • 59
  • 2
0

According to JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS (december 2005):

AV Rule 67

Public and protected data should only be used in structs—not classes. Rationale: A class is able to maintain its invariant by controlling access to its data. However, a class cannot control access to its members if those members non-private. Hence all data in a class should be private.

Thus, the "m" prefix becomes unuseful as all data should be private.

But it is a good habit to use the p prefix before a pointer as it is a dangerous variable.

Community
  • 1
  • 1
0

Many of those conventions are from a time without sophisticated editors. I would recommend using a proper IDE that allows you to color every kind of variable. Color is by far easier to spot than any prefix.

If you need to get even more detail on a variable any modern IDE should be able to show it to you by moving the caret or cursor over it. And if you use a variable in a wrong way (for instance a pointer with the . operator) you will get an error, anyway.

0

Personally I use a relatively "simple" system to denote what variables are

I have the different "flags" that I combine then an underscore, then the memory type, then finally the name.

I like this because you can narrow down the amount of variables in an IDE's completion as much as possible as quickly as possible.

The stuff I use is:

m for member function
s for static
c for const/constexpr

then an underscore _

then the variable memory type

p for unowned pointer
v for list
r for reference
nothing for owned value

for example if I had a member variable which is a list of ints I would put

m_vName

and for a static const pointer to a pointer of lists of ints I would put

sc_ppvName

This lets me quickly tell what The variable is used for and how to access it. aswell as how to get/drop values

0

Wrap all private data with a struct

class Demo {
public:
    Demo() {
        self.name = "Harry Porter";
        self.age = 18;
    }
protected:
    struct self_type {
        std::string name;
        int age;
    } self = {};
};
Sunding Wei
  • 1,803
  • 17
  • 12
  • Please don't. Dollar is not portable. https://stackoverflow.com/questions/26301737/does-c11-allow-dollar-signs-in-identifiers – vines Nov 18 '22 at 14:57