Const Before or Const After

Const before or const after?

why is there two correct ways of specifying const data and in what situation would you prefer or need one over the other if any?

Essentially, the reason that the position of const within specifiers prior to an asterisk does not matter is that the C grammar was defined that way by Kernighan and Ritchie.

The reason they defined the grammar in this way was likely that their C compiler parsed input from left-to-right and finished processing each token as it consumed that. Consuming the * token changes the state of the current declaration to a pointer type. Encountering const after * means the const qualifier is applied to a pointer declaration; encountering it prior to the * means the qualifier is applied to the data pointed to.

Because the semantic meaning does not change if the const qualifier appears before or after the type specifiers, it is accepted either way.

A similar sort of case arises when declaring function pointers, where:

  • void * function1(void) declares a function which returns void *,

  • void (* function2)(void) declares a function pointer to a function which returns void.

Again the thing to notice is that the language syntax supports a left-to-right parser.

Why using the const keyword before and after method or function name?

const T& get_data() const { return data_; }
^^^^^

means it will return a const reference to T (here data_)

Class c;
T& t = c.get_data() // Not allowed.
const T& tc = c.get_data() // OK.




const T& get_data() const { return data_; }
^^^^^

means the method will not modify any member variables of the class (unless the member is mutable).

void Class::get_data() const {
this->data_ = ...; // is not allowed here since get_data() is const (unless 'data_' is mutable)
this->anything = ... // Not allowed unless the thing is 'mutable'
}

Const before or after the type?

Cv-qualifiers like const apply to whatever is to the left of them, unless there is nothing, in which case they apply to the right. For string const&, the const applies to the string to its left. For const string&, the const applies to the string to its right. That is, they're both references to const string, so in this case, it makes no difference.

Some people prefer to have it on the left (like const int) because it reads from left to right. Some people prefer to have it on the right (like int const) to avoid using the special-case (int const * const is more consistent than const int* const, for example).

Does const keyword go before or after Type?

How does const work? It is always applied to what comes right before it. However, when there is nothing before, it applies to what comes right after it. In other words, const Type& is the same as Type const&.

Now, do not ever use preprocessor macros to define type aliases. There are two ways of doing that in C++: using and typedef. The fact you used a macro is the reason why you observe this peculiar behaviour. The code that fails to compile is expanded to the following:

void fun(const C*& p); // The pointee is const, but the pointer itself is not

I suppose you are then doing things on the object pointed by p... But this object is const! In the second example, the expansion results in:

void fun(C* const& p); // The pointee is not const, but the pointer itself is

Then, you are doing stuff on the pointee but this time it's the pointer, not the pointee, that is const, so everything is fine. If you had used an alias or a typedef, it would have gone perfectly fine in both cases: see this example.

As a rule of thumb, you should always put const on the right of the thing you want it to be applied to. This would allow you to read types the way they are meant to be read: from right to left.

C++: const reference, before vs after type-specifier

No difference as const is read right-to-left with respect to the &, so both represent a reference to an immutable Fred instance.

Fred& const would mean the reference itself is immutable, which is redundant; when dealing with const pointers both Fred const* and Fred* const are valid but different.

It's a matter of style, but I prefer using const as a suffix since it can be applied consistently including const member functions.

C++ Difference between const positioning

const int MyClass::showName(string id) returns a const int object. So the calling code can not change the returned int. If the calling code is like const int a = m.showName("id"); a = 10; then it will be marked as a compiler error. However, as noted by @David Heffernan below, since the integer is returned by copy the calling code is not obliged to use const int. It can very well declare int as the return type and modify it. Since the object is returned by copy, it doesn't make much sense to declare the return type as const int.

int MyClass::showName(string id) const tells that the method showName is a const member function. A const member function is the one which does not modify any member variables of the class (unless they are marked as mutable). So if you have member variable int m_a in class MyClass and if you try to do m_a = 10; inside showName you will get a compiler error.

Third is the combination of the above two cases.

What is meant with const at end of function declaration?

A "const function", denoted with the keyword const after a function declaration, makes it a compiler error for this class function to change a member variable of the class. However, reading of a class variables is okay inside of the function, but writing inside of this function will generate a compiler error.

Another way of thinking about such "const function" is by viewing a class function as a normal function taking an implicit this pointer. So a method int Foo::Bar(int random_arg) (without the const at the end) results in a function like int Foo_Bar(Foo* this, int random_arg), and a call such as Foo f; f.Bar(4) will internally correspond to something like Foo f; Foo_Bar(&f, 4). Now adding the const at the end (int Foo::Bar(int random_arg) const) can then be understood as a declaration with a const this pointer: int Foo_Bar(const Foo* this, int random_arg). Since the type of this in such case is const, no modifications of member variables are possible.

It is possible to loosen the "const function" restriction of not allowing the function to write to any variable of a class. To allow some of the variables to be writable even when the function is marked as a "const function", these class variables are marked with the keyword mutable. Thus, if a class variable is marked as mutable, and a "const function" writes to this variable then the code will compile cleanly and the variable is possible to change. (C++11)

As usual when dealing with the const keyword, changing the location of the const key word in a C++ statement has entirely different meanings. The above usage of const only applies when adding const to the end of the function declaration after the parenthesis.

const is a highly overused qualifier in C++: the syntax and ordering is often not straightforward in combination with pointers. Some readings about const correctness and the const keyword:

Const correctness

The C++ 'const' Declaration: Why & How



Related Topics



Leave a reply



Submit