9

I know that if you write void function_name(int& a), then function will not do local copy of your variable passed as argument. Also have met in literature that you should write void function_name(const int & a) in order to say compiler, that I dont want the variable passed as argument to be copied.

So my question: what is the difference with this two cases (except that "const" ensures that the variable passed will not be changed by function!!!)???

Narek
  • 38,779
  • 79
  • 233
  • 389
  • Is it not the difference between `const int & a` and `int a` or even `const int a` the real point ? I wonder why the compiler should make any difference between `const int & a` and `const int a` ? Or does using & garantee that compiler will not do a copy and `const int a` force it making a copy ? How can you say 'leave the compiler choose' ? – kriss Apr 28 '10 at 07:17
  • See also here: http://stackoverflow.com/questions/2139224/2139254#2139254 – sbi Apr 28 '10 at 07:37
  • 1
    @kriss: The compiler cannot choose. Consider that you declare a function `void f( int x );`. At the point of declaration the compiler has no information on whether you will or not change the object. Only seeing the code it can assert that the code does not change or does change the parameter. And even then, if the code changes a parameter, how can the compiler know whether you want that change to be visible outside of the function? Even if it could decide with the definition, how would the compiler consider the signature in translation units where only the header is included? – David Rodríguez - dribeas Apr 28 '10 at 07:43
  • @David: OK, so it's a linking problem. And I guess when inlining the compiler can optimize differences away anyway. – kriss Apr 28 '10 at 09:04
  • 1
    It is more of a problem of knowledge: the compiler knows what you tell it, not what you meant to tell it. And that is not only a problem at link time, it can be within the same translation unit: you declare the function, use it, and later define it. At the point of use the compiler has not yet seen the definition and could not guess. – David Rodríguez - dribeas Apr 28 '10 at 09:16

7 Answers7

11

You should use const in the signature whenever you do not need to write. Adding const to the signature has two effects: it tells the compiler that you want it to check and guarantee that you do not change that argument inside your function. The second effect is that enables external code to use your function passing objects that are themselves constant (and temporaries), enabling more uses of the same function.

At the same time, the const keyword is an important part of the documentation of your function/method: the function signature is explicitly saying what you intend to do with the argument, and whether it is safe to pass an object that is part of another object's invariants into your function: you are being explicit in that you will not mess with their object.

Using const forces a more strict set of requirements in your code (the function): you cannot modify the object, but at the same time is less restrictive in your callers, making your code more reusable.

void printr( int & i ) { std::cout << i << std::endl; }
void printcr( const int & i ) { std::cout << i << std::endl; }
int main() {
   int x = 10;
   const int y = 15;
   printr( x );
   //printr( y ); // passing y as non-const reference discards qualifiers
   //printr( 5 ); // cannot bind a non-const reference to a temporary
   printcr( x ); printcr( y ); printcr( 5 ); // all valid 
}
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
8

So my question: what is the difference with this two cases (except that "const" enshures that the variable passes will not be changed by function!!!)???

That is the difference.

Alex Budovski
  • 17,947
  • 6
  • 53
  • 58
  • I meen from the aspect of copy. – Narek Apr 28 '10 at 07:23
  • @Narek: the `const` doesn't affect whether or not a copy is performed. Passing by reference (`const` or not) will avoid a copy. Passing by value (not using a reference) will cause a copy, whether the parameter is `const` or not. Using a `const` reference parameter for an `int` is generally considered unnecessary, since passing by value has no additional cost in that case. – Michael Burr Apr 28 '10 at 07:27
  • @Michael: and what about `const int` vs `int` ? – kriss Apr 28 '10 at 09:19
  • 1
    the `int` is passed by copy both times, the former ensuring that the function doesn't change it. (But this doesn't matter much for the caller, since it only can change its copy of it). Though this can prevent accidental change, in the same way `const` is used when declaring local variables. – Alex Budovski Apr 28 '10 at 09:23
1

You state the difference right. You may also formulate it as:

If you want to specify that the function may change the argument (i.e. for init_to_big_number( int& i ) by specifying the argument by (variable) reference. When in doubt, specify it const.

Note that the benefit of not copying the argument is in performance, i.e. for 'expensive' objects. For built-in types like int it makes no sense to write void f( const int& i ). Passing the reference to the variable is just as expensive as passing the value.

xtofl
  • 40,723
  • 12
  • 105
  • 192
1

There is a big difference in terms of parameter they could operate on, Say you have a copy constructor for your class from int,

customeclass(const  int & count){
  //this constructor is able to create a class from 5, 
  //I mean from RValue as well as from LValue
}
customeclass( int  & count){
  //this constructor is not able to create a class from 5, 
  //I mean only from LValue
}

The const version can essentially operate on temporary values and non constant version could not operate on temporary, you would easily face issue when you miss out const where it is needed and use STL, but you get weired error telling it could not find the version that takes temporary. I recommend use const where ever you can.

yesraaj
  • 46,370
  • 69
  • 194
  • 251
0

They are used for different purposes. Passing a variable using const int& ensures you get the pass-by-copy semantics with much better performance. You are guaranteed that the called function (unless it does some crazy things using const_cast) will not modify your passed argument without creating a copy. int& is used when there are generally multiple return values from a function. In that case these can be used hold the results of the function.

Naveen
  • 74,600
  • 47
  • 176
  • 233
  • 3
    But you don't get pass by copy semantics with `const int&`. External changes to the passed object will be visible inside the called function. This is definitely not a pass by copy semantic, it is a feature of pass by reference. – CB Bailey Apr 28 '10 at 07:16
0

I would say that

void cfunction_name(const X& a);

allows me to pass a reference to temporary object as follows

X make_X();

function_name(make_X());

While

void function_name(X& a);

fails to achieve this. with the following error error: invalid initialization of non-const reference of type 'X&' from a temporary of type 'X'

Vicente Botet Escriba
  • 4,305
  • 1
  • 25
  • 39
0

leaving out the performance discussion, let the code speak!

void foo(){
    const int i1 = 0;
    int i2 = 0;
    i1 = 123; //i gets red -> expression must be a modifiyble value
    i2 = 123;
}
//the following two functions are OK
void foo( int i ) {
    i = 123;
}
void foo( int & i ) {
    i = 123;
}
//in the following two functions i gets red
//already your IDE (VS) knows that i should not be changed
//and it forces you not to assign a value to i
//more over you can change the constness of one variable, in different functions
//in the function where i is defined it could be a variable
//in another function it could be constant 
void foo( const int i ) {
    i = 123; 
}
void foo( const int & i ) {
    i = 123; 
}

using "const" where it is needed has the following benefits: * you can change the constness of one variable i, in different functions in the function where i is defined it could be a variable in another function it could be constant value. * already your IDE knows that i should not be changed. and it forces you not to assign a value to i

regards Oops

OlimilOops
  • 6,747
  • 6
  • 26
  • 36