754

I got a book, where there is written something like:

class Foo 
{
public:
    int Bar(int random_arg) const
    {
        // code
    }
};

What does it mean?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
aPoC
  • 7,633
  • 3
  • 16
  • 8
  • 33
    It changes the type of `this` from `Foo* const` into `const Foo* const`. That has consequences. – sbi Jun 29 '10 at 13:55
  • I don't understand your edit. What exactly do you wanna know? If declaring two variables of type Foo will create multiple functions instances of Bar? – Janick Bernet Jun 29 '10 at 14:06
  • @inflagranti: Yes, exactly this I wanna know. – aPoC Jun 29 '10 at 14:08
  • Then the answer is no. And why did you assume it would be? – Janick Bernet Jun 29 '10 at 14:10
  • Some friend told me somewhen... But without the const-tag, would it ? – aPoC Jun 29 '10 at 14:18
  • 8
    @aPoC functions (or here methods) only exist once "in memory" (being `static` or not, it doesn't matter). They get passed a hidden parameter `this` which is a pointer to the calling instance. – ereOn Jun 29 '10 at 14:19
  • @sbi I think it should be "from `Foo*` into `const Foo*`". `this` is *not* a constant pointer. In the past, some implementations used constant pointer for `this`, as a trick, though. I think [this answer](https://stackoverflow.com/a/6067267/10027592) explained it nicely. – starriet Aug 18 '22 at 14:00
  • @starriet: Ah, **`this`** is an rvalue, but not **`const`**, right? So my comment was technical wrong, but, sadly, I cannot fix it anymore. – sbi Aug 28 '22 at 17:58

6 Answers6

1232

A "const function", denoted with the keyword const after a function declaration, makes it a compiler error for this class function to change a data member 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 data members 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

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Janick Bernet
  • 20,544
  • 2
  • 29
  • 55
  • 7
    @ereOn, if you liked mutable, you might like this. The most common use-case for "mutable" is as a modifier for a mutex controlling access to a class instance. Just because you promise not to modify the instance, doesn't mean that what you read from it won't be modified by someone else holding a non-const reference to it. – Dmitry Rubanovich Apr 05 '15 at 21:12
  • 3
    @Janick, I've been learning c++ by myself for a year or two, never see any books cover an explanation like this and I feel it's really helpful. What type of books shall I read to learn these things like this implicit this pointer. – Steven Oct 10 '15 at 17:41
  • 5
    @Steven: I think the most helpful thing might be to actually read a C book and how some OO like things can be implemented in plain C. From that it's the more easily to see how C++ native OO functionality maps on more lower-level constructs in C and eventually down to the machine. – Janick Bernet Oct 12 '15 at 07:05
  • A great answer. But I find the 2nd paragraph a bit hard to read, not sure how the text can be improved though. Also if I understand correctly non-member function `Foo_Bar(&f, 4);` won't be able to access member variables in `f` (whether it's const or non-const case), because usually member variables are `private` – artm Feb 04 '17 at 00:04
  • 2
    2 more important points to note: 1) Static data members can still be modified. 2) Bitwise constness is checked here which means that the memory of the object which called the function is checked bit by bit and no change should be made in it. Which further tells us, If there is a int* data member, then the adress that this pointer contains inside the object memory cannot change, but the value at that location which is not part of object memory can change. – Sukrit Gupta Jan 23 '19 at 04:18
  • @artm checking access is over and done *before* that. Janick is not describing a pre-processing step. A toolchain will often share a linker between C and C++, in those cases there literally *are* C callable functions as described here, with an extra parameter corresponding to `this` – Caleth Jun 04 '19 at 08:24
  • What if a const function does not directly change a value, but calls another function that changes a value? – Lukas Thiersch Nov 22 '19 at 12:14
  • 2
    @LukasThiersch, if const function calls non-const function to change the value, compiler throws **error**. – Eswaran Pandi Mar 12 '20 at 11:43
72

Consider two class-typed variables:

class Boo { ... };

Boo b0;       // mutable object
const Boo b1; // non-mutable object

Now you are able to call any member function of Boo on b0, but only const-qualified member functions on b1.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
21

Bar is guaranteed not to change the object it is being invoked on. See the section about const correctness in the C++ FAQ, for example.

mkluwe
  • 3,823
  • 2
  • 28
  • 45
14

Similar to this question.

In essence it means that the method Bar will not modify non mutable member variables of Foo.

John Warlow
  • 2,922
  • 1
  • 34
  • 49
10

I always find it conceptually easier to think of that you are making the this pointer const (which is pretty much what it does).

Goz
  • 61,365
  • 24
  • 124
  • 204
9

Function can't change its parameters via the pointer/reference you gave it.

I go to this page every time I need to think about it:

http://www.parashift.com/c++-faq-lite/const-correctness.html

I believe there's also a good chapter in Meyers' "More Effective C++".

orbfish
  • 7,381
  • 14
  • 58
  • 75