arc_lupus
arc_lupus

Reputation: 4114

Why should I not use `const` in this simple function?

When learning C++, one of the first functions one gets for learning the concept of a function is something like

int add(int a, int b)
{
    return a+b;
}

Now I was wondering: Should I use the const-keyword here, or rather not, resulting in

int add(const int a, const int b)
{
    return a+b;
}

But would that make sense? Would it speed my program up, do some other important stuff, or just increase confusion?

Upvotes: 16

Views: 8403

Answers (10)

Andrew
Andrew

Reputation: 1470

I feel like everyone is dancing around this part of the answer... It's true that using const will keep the function from modifying the value of your int a & b while inside the function. This can be extremely useful, so use it as you wish, of the compiler allows it. But, the function caller will never know about any changes to a & b once the function finishes. So even if a & b are changed, no one except the defined function will know their updated values.

int funcB(int a, int b)
{
    a = a+1;
    b = b*b;
    return a+b;
}

void funcA()
{
    int s = 5;
    int t = 6;
    int result = funcB(s, t);
    printf("%f + %f = %f", s,t, result);
}

funcA prints: "5 + 6 = 42"

Const protection is often used when passing values by reference, ie:

int function(const int &a, const int &b) {}

This passes a reference of a and b to the function (ie, does not make copies of a and b but passes only a memory address of that variable, aka: the handle). When passing a variable by reference, any changes made to the variable are remembered outside the scope of the function and can change the way your program runs. This is generally undesired behavior. So if you rework funcB from above and pass by reference:

int funcB(int &a, int &b)
{
    a = a+1;
    b = b*b;
    return a+b;
}

funcA prints: "6 + 36 = 42"

If you add const correctness to funcB:

int funcB(const int &a, const int &b)
{
    a = a+1;
    b = b*b;
    return a+b;
}

I don't think the compiler will let you even do this since you would be explicitly trying to modify values that you've protected via const.

Another time when it may be really important to use const is when you're passing by pointer, instead of reference or copy...

int funcB(int *a, int *b)
{
    a = a+1;
    b = b*b;
    return a+b;
}

Unless you're a pointer expert, avoid passing pointers without const pretention. This func will likely attempt to iterate the index of your pointer arrays and you'd open yourself up to run time errors related to out of bound memory. You could accidently see memory from an entirely different program... but probably not.

Lastly, since you're just passing int, there's no practical need to pass by reference (which is done often to keep from adding complex data into memory because each non-reference or non-pointer pass to functions copies the value into memory for the life of the function being called) since the memory footprint of int is so small. Unless, you're working with specialized hardware that has extremely limited memory, then it may be useful; this won't apply to most standard computers and desktops made within the past 20 years, or smart phones.

Upvotes: 1

Raindrop7
Raindrop7

Reputation: 3911

as a law of thumb we are advised to use const as much as possible because we get a great help from the compiler so whenever we try to change a constant the mistake will be caught by the compiler; it's a good thing avoiding being caught in error-prones.

the second thing: a and b passed by value so they are created as local constants But as long as they are not changeable why we need copies??

  • the good thing is to pass a const reference which means never change parameters and avoid copies (by value):

    int add(const int& a, const int& b) // now there are no copies of a and b in addition we cannot modify a and be
    {
        return a+b;
    }
    

Upvotes: 0

Wissam HANNA
Wissam HANNA

Reputation: 63

The primary purpose of constness is to provide documentation and prevent programming mistakes. Const allows you to make it clear to yourself and others that something should not be changed. Moreover, it has the added benefit that anything that you declare const will in fact remain const short of the use of forceful methods. It's particularly useful to declare reference parameters to functions as const references:

bool SomeFunction (const myObj& obj);

Here, a myObj object is passed by reference into SomeFunction. For safety's sake, const is used to ensure that SomeFunction cannot change the object--after all, it's just supposed to make sure that the object is in a valid state. This can prevent silly programming mistakes that might otherwise result in damaging the object (for instance, by setting a field of the class for testing purposes, which might result in the field's never being reset). Moreover, by declaring the argument const, users of the function can be sure that their object will not be changed and not need to worry about the possible side effects of making the function call.

moreover, The reason is that const for the parameter only applies locally within the function, since it is working on a copy of the data. This means the function signature is really the same anyways. It's probably bad style to do this a lot though. I personally tend to not use const except for reference and pointer parameters.

Upvotes: 0

Bathsheba
Bathsheba

Reputation: 234655

Using int add(const int a, const int b) means that you cannot modify the input parameters within the function body.

Perhaps the compiler can make some optimisations based on that, so it ought therefore to be never slower than the non-const equivalent. But I have never observed this effect in practice.

Passing const parameters can also increase the stability of your code base, particularly in a collaborative project.

All this said though, I find it too verbose, rather unnecessary, and would use int add(int a, int b). Very occasionally, for particularly long functions, I exploit the fact that you can declare the function with non-const parameters, and define it with the parameters const.

Upvotes: 7

Kerrek SB
Kerrek SB

Reputation: 476970

If you are actually struggling with correctness bugs in your codebase where const would have helped, then add const.

That said, there are related issues that you should consider. Top-level qualifiers of function parameters aren't part of the function type, so your function type is still just int(int, int). (The qualifiers only affect the parameter variables in the function definition.) That means that any declaration of the function also ignores qualifiers, so int add(int, int) and int add(const int, int) and int add(int, const int) all declare the same function. So you have to decide on a policy for how you write header files. And now you have three essential positions you can take:

  1. Always qualify in both declaration and definition. The upside is that this perhaps keeps code looking "consistent" (think copy/pasting when creating implementations). The downside is that the qualifiers have nothing to do with the interface, and are not at all enforcible (you can change the definition later!), so at best it's noise, at worst it's wrong.

  2. Qualify in the definition, but not in the other declarations. The upside is that this communicates the interface correctly and you still get const checking in the definition. The downside is that some people might be confused by the discrepancies in spelling. (Just like people may be confused that a static constexpr T foo; class member can be defined with const T C::foo;.)

  3. Don't qualify either. The upside is that it's consistent, clean, easy to remember and minimal. The downside is that you're missing out on correctness checks in your definition.

There's no right answer. If you're the codebase owner or project lead, you should decide based on what the biggest problems in your codebase and team are. (My personal position is to stick with (3) until you have a good reason to change.)

Upvotes: 7

Saket Arora
Saket Arora

Reputation: 1

If you will use const then you cannot modify the value of a,b. Thats why we don't use const.

Upvotes: 0

GrahamS
GrahamS

Reputation: 10350

You can use const there if you like.

It is unlikely to speed up your program because any reasonable compiler can already see that no code path alters the value of a or b and make any optimisations it needs.

a and b are int, which are passed by value so making them const has no impact on the users of this function.

The only possible advantage is where your function is long and more complex and you want to avoid possible programming errors where the original values of a or b are changed during the function.

Upvotes: 0

UKMonkey
UKMonkey

Reputation: 6983

If you want to be truly const correct, then you should add it, but in reality all it will do is make you type and read more.

Nothing will go faster, and while it could mean that your variables go into another location in memory, it's unlikely to on most modern machines.

What it will stop you doing is accidentally assigning them values, but as they're local to the function, it's relatively unimportant. What would matter is if they were references, as this demonstrates your intent to the caller to not change them.

Upvotes: 0

Ajay Pal
Ajay Pal

Reputation: 563

int add(const int a, const int b)
{
    return a+b;
}

Here const in used so that the function does not modify the original values of a and b by any chance. In the above example it does not make sense. But if it would have been an example like

int add(const int *a, const int *b)
{
    //*a = 10; //This will throw error. 
    return a+b;
}

In functions where objects,arrays or such data types are passed its a good approach to use const to avoid mutation of original data structure.

Upvotes: 0

Mr.C64
Mr.C64

Reputation: 42924

From the caller's perspective, both the first and the second form are the same.

Since the integers are passed by value, even if the function modifies a and b, the modified values are copies of the original and won't be visible to the caller.

However, from the function implementer's perspective there's a difference. In fact, in the second form:

int add(const int a, const int b)

you will get a compiler error if you try to modify the values of a and b inside the function's body, as they are marked as const.

Instead, you can change those values if you omit the const.
Again, those modifications will not be visible to the caller.

Upvotes: 16

Related Questions