C++ - constant value for reference parameter? - c++

Usually, parameter values are copied when being passed on. Using a reference may save memory, especially for big structs. However, in this case:
void foo( int parameter = 7 );
void bar( const int& parameter = 7 );
in the second declaration, what exactly will it do when the default value is used? What happens when a constant value is used for a reference parameter?
void foo( const int& parameter ) { }
...
foo( 7 );
is there any difference in efficiency between a reference and a copied value when a contant value is used?

1) It will do the same thing as if it wasn't const&. You can't modify const& parameters, so you're OK to bind them to constants1.
2) There might be a very tiny difference in efficiency because you're really (probably, implementation dependent) passing a pointer to the value instead of the value, so you'll have to dereference the pointer to get to the real value. (Then again, the compiler could see that passing an int by const reference is a waste of time so it will pass the thing by value and pretend to you that it's by const reference. You can't know.) This sacrifice may be worth it for larger constructs, but generally you don't ever need to pass something like int by const reference.
1 mcmcc pointed out that in the case of integer literals, you are really binding the the reference to a location on the stack (unlike string literals, for instance, which reside in static memory).

References to const are special: they extend the lifetime of temporary objects.
Compare:
struct Foo { Foo(int, int) { } };
{
Foo(1,2); // dies!
const Foo & f = Foo(3,3); // lives...
// ...
} // ... now it's dead
In the same way, if you don't provide an integer, a temporary integer is constructed, and its lifetime is extend to the duration of the function call by virtue of being bound to parameter.
See Herb Sutter's GotW #88.

Related

Reference from literal

I am calling a function with the signature
void setValue(int& data)
I would like to pass a literal number to it:
setValue(1);
But I get:
error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
Is there a way I can make this work without changing the function (it's in a library) and without assigning each literal value to a variable?
Assuming setValue does not actually modify its argument and just has a wrong signature which you cannot change, here is an approach which is not thread-safe among other things:
#include <iostream>
void setValue(int &i)
{
std::cout << "i = " << i << std::endl;
}
int& evil(int i)
{
static int j;
j = i;
return j;
}
int main()
{
setValue(evil(1));
setValue(evil(2));
}
When you declare the argument as being an int&, you are saying that the function called can change the value and the caller will see the change.
So it is no longer valid to pass a literal value then because how could the function possibly change the given value of a literal?
If you don't want the setValue to be able to change the given value, make the argument either be an int or const int&. And if you do want the setValue function to be able to change the value, then the caller must declare a non-const variable to hold the int and pass in that.
Can I change something at the call site to make it work
The problem with your code is that you declared your function to expect a reference, which means the compiler has to prepare the code to allow the function to change whatever you pass into it at the call site. So yes, sure, you can declare a variable, set it to 1 and call your function with it.
Contrast this with a constant reference in the declaration, where the compiler knows you won't change it inside the function, and then you can pass a literal in without issues. In fact, any logical, thought out design will make setters accept constant parameters because it won't change them, it will just store a possibly processed value in its state.
The answer to „what do I do if a library has a bad interface and I can't change it“ is usually „write a wrapper“. Assuming this is a method of some class BadLibraryClass, you could do something like:
class Wrapper {
public:
BadLibraryClass inner;
setValue(int i) {
inner.setValue(i); // i is an lvalue
}
};
This is just a crude example. Perhaps inner is better off being a pointer, a reference or even a smart pointer. Perhaps you want a conversion operator to BadLibraryClass. Perhaps you can use inheritance to expose other methods of BadLibraryClass.
Two options:
Use the result of assignment:
static int _data;
void myCall() {
setValue((_data = 3));
}
Write a wrapper:
struct setValueW {
int _data;
// constructor
setValueW(int _data) : _data(_data) {
setValue(_data);
}
// if you want to call it again
void operator()() {
setValue(_data);
}
};
void myCall2() {
setValueW(3);
}
AFAIK, references keeps the addresses of the variable. 1 is not variable. It is temporary.
Take a look this article(this is a quote from this site)
c++11 introduced a new kind of reference variable -- an r-value reference
To declare one, use && after a type
int & // type designation for an L-value reference
int && // type designation for an R-value reference
L-value references can only refer to L-values
R-value references can reference to R-values (temporaries)
int x, y, z; // regular variables
int & r = x; // L-value reference to the variable x
int & r2 = x + y; // This would be ILLEGAL, since x + y is an R-value
int && r3 = x + y; // LEGAL. R-value reference, referring to R-value
So you can use (But this is not useful. It may be more useful if you write this in plain without rvalue or lvalue.):
void setValue(int&& data)
setValue(1);
Or you can use that:
void setValue(int& data)
int a = 11;
setValue(a);
Don't forget for second example. If you change the value of data parameter. You will have change the a variable value.
No, you can't.
An lvalue reference like that binds to a variable (roughly speaking).
Your literal is not such a thing. It never had a name, and may not even have a home in memory.
Your two options are the two things you ruled out, I'm afraid.
For what it's worth, this is not your fault: that is a rather poor setter. It should take const int& (which will automatically create a nice temporary variable for you out of the literal!), or even just const int.

Why cannot assign value to non-const reference?

Why these definitions are all ok:
int func(int p=255) {
return p;
}
int func1(const int &p=255) {
return p;
}
but this definition:
int func2(int &p=255) {
return p;
}
leads to compile error ?
What is the logic behind it ?
Taking arguments by reference means, you dont work with your local copy of the variable, but with a variable already defined in the scope of the calling function.
While your first example makes sense (you have a local variable p that you can fill with a default value) the second example is a bit more tricky: Usually when using references you expect the variable to have an address, since you want to modify it. For const-refernces, the compiler will still allow you to pass a literal, even if something like "reference to a literal" makes no sense at all.
In the third case the compiler expects you to modify p. But what part of the memory should this modification affect? "255" has no address - therefore it cant be used as a reference.
If you want to have a more detailed explanation, you should probably look for keywords like "rvalue" and "lvalue".
The attempted function definition
auto func2( int& p = 255 )
-> int
{ return p; }
… fails because you can't bind an rvalue to a reference to non-const. Basically that rule is because a simple value like 255 isn't modifiable. While the reference can be used to modify.
One simple solution is to express the default as a separate overload:
auto func2( int& p )
-> int
{ return p; }
auto func2()
-> int
{
int scratchpad = 255;
return func2( scratchpad );
}
A non-const reference must be bound to lvalue (i.e. its address could be got). 255 (i.e. an int literal) is not a lvalue, so int &p=255 fails.
A const reference could be bound to rvalue, and for this case, a temporary int will be created and initialized from 255. The temporary int's lifetime will be the same as the const reference.
int func(int p=255) {
return p;
}
p here is copied by value, and it is defined to exist in the scope of func.
int func2(int &p) {
return p;
}
// e.g. use:
int value = 10;
func2(value); // func2 *could* modify value because it is passed by non-const reference
In this case the compiler here expects p to have a name somewhere in memory (i.e. lvalue), so it can possibly write to it within func2. Passing by non-const reference allows you to modify the variable used in the function call. Since p must belong to someone else somewhere since it can be modified, you can't assign a default value to it.
But what about the const-reference case? Here, the compiler is smart enough to know that p can never be written to since it is const, so it doesn't need to have a name in memory to write to. In cases of a literal being passed (e.g. 255), it (behind the scenes) essentially creates a temporary and passes that temporary variable to the function.
int func1(const int &p=255) {
return p;
}
func1(10);
// Behind the scenes, the compiler creates something along these lines
// since it can never be modified.
const int some_temporary = 10;
func1(some_temporary);

c++ const member function that returns a const pointer.. But what type of const is the returned pointer?

I apologize if this has been asked, but how do I create a member function in c++ that returns a pointer in the following scenerios:
1. The returned pointer is constant, but the junk inside can be modified.
2. The junk inside is constant but the returned pointer can be modified.
3. Neither the junk, nor the pointer can be modified.
Is it like so:
int *const func() const
const int* func() const
const int * const func() const
All of the tutorials I've read don't cover this distinction.
Side note:
If my method is declared const then the tutorials say that I'm stating that I won't modify the parameters.. But this is not clear enough for me in the case when a parameter is a pointer. Do my parameters need to be like:
a. void func(const int* const x) const;
b. void func(const int* x) const;
c. void func(const int* const x) const;
I don't know what book you have read, but if you mark a method const it means that this will be of type const MyClass* instead of MyClass*, which in its turn means that you cannot change nonstatic data members that are not declared mutable, nor can you call any non-const methods on this.
Now for the return value.
1 . int * const func () const
The function is constant, and the returned pointer is constant but the 'junk inside' can be modified. However, I see no point in returning a const pointer because the ultimate function call will be an rvalue, and rvalues of non-class type cannot be const, meaning that const will be ignored anyway
2 . const int* func () const
This is a useful thing. The "junk inside" cannot be modified
3 . const int * const func() const
semantically almost the same as 2, due to reasons in 1.
HTH
Some uses of const don't really make much sense.
Suppose you have the following function:
void myFunction (const int value);
The const tells the compiler that value must not change inside the function. This information does not have any value for the caller. It's up to the function itself to decide what to do with the value. For the caller, the following two function definitions behave exactly the same for him:
void myFunction (const int value);
void myFunction (int value);
Because value is passed by value, which means that the function gets a local copy anyway.
On the other hand, if the argument is a reference or a pointer, things become very different.
void myFunction (const MyClass &value);
This tells the caller that value is passed by reference (so behind the screens it's actually a pointer), but the caller promises not to change value.
The same is true for pointers:
void myFunction (const MyClass *value);
We pass a pointer to MyClass (because of performance reasons), but the function promises not to change the value.
If we would write the following:
void myFunction (MyClass * const value);
Then we are back int he first situation. myFunction gets a pointer, which is passed by value, and which is const. Since MyFunction gets a copy of the pointer value, it doesn't matter for the caller whether it is const or not. The most important thing is that myFunction can change the contents of value, because the pointer variable itself is const, but the contents in it isn't.
The same is true for return values:
const double squareRoot(double d);
This doesn't make any sense. squareRoot returns a const double but since this is passed 'by value', and thus needs to be copied to my own local variable, I can do whatever I want with it.
On the other hand:
const Customer *getCustomer(char *name);
Tells me that getCustomer returns me a pointer to a customer, and I am not allowed to change the contents of the customer.
Actually, it would be better to make the char-pointer-contents const as well, since I don't expect the function to change the given string:
const Customer *getCustomer(const char *name);
int *const func() const
You cannot observe the const here except for a few cases
Taking the address of func.
In C++0x, directly calling func with the function-call syntax as a decltype operand, will yield int * const.
This is because you return a pure pointer value, that is to say a pointer value not actually stored in a pointer variable. Such values are not const qualified because they cannot be changed anyway. You cannot say obj.func() = NULL; even if you take away the const. In both cases, the expression obj.func() has
the type int* and is non-modifiable (someone will soon quote the Standard and come up with the term "rvalue").
So in contexts you use the return value you won't be able to figure a difference. Just in cases you refer to the declaration or whole function itself you will notice the difference.
const int* func() const
This is what you usually would do if the body would be something like return &this->intmember;. It does not allow changing the int member by doing *obj.func() = 42;.
const int * const func() const
This is just the combination of the first two :)
Returning a pointer to const makes a lot of sense, but returning a const pointer (you cannot modify) usually adds no value (although some say it can prevent user errors or add compiler optimisation).
That is because the return value belongs to the caller of the function, i.e. it is their own copy so it doesn't really matter if they modify it (to point to something else). The content however does not "belong" to the caller and the implementor of the function may make a contract that it is read-only information.
Const member functions promise not to change the state of the class, although this is not necessarily enforced in reality by the compiler. I am not referring here to const_cast or mutable members so much as the fact that if your class itself contains pointers or references, a const member function turns your pointers into constant pointers but does not make them pointers to const, similarly your references are not turned into references-to-const. If these are components of your class (and such components are often represented by pointers) your functions can change their state.
Mutable members are there for the benefit of allowing your class to change them whilst not changing internal state. These can typically be applied to:
Mutexes that you wish to lock even for reading.
Data that is lazy-loaded, i.e. filled in the first time they are accessed.
Reference-counted objects: You want to increase the reference count if it has another viewer, thus you modify its state just to read it.
const_cast is generally considered a "hack" and is often done when someone else has not written their code properly const-correct. It can have value though in the following situations:
Multiple overloads where one is const and one non-const and the const returns a const-reference and the non-const returns a non-const reference, but otherwise they are the same. Duplicating the code (if it is not a simple data member get) is not a great idea, so implement one in terms of the other and use const_cast to get around the compiler.
Where you want in particular to call the const overload but have a non-const reference. Cast it to const first.
The const method prevents you from modifying the members. In case of pointers, this means you can't reassign the pointer. You can modify the object pointed at by the pointer to your heart's desire.
As the pointer is returned by value (a copy), the caller can't use it to modify the pointer member of the class. Hence adding const to the return value adds nothing.
Things are different if you were to return a reference to the pointer. Now, if the pointer weren't const, this would mean that a function that doesn't have rights to modify a value is granting this right to the caller.
Example:
class X
{
int* p;
public:
int* get_copy_of_pointer() const //the returned value is a copy of this->p
{
*p = 42; //this being const doesn't mean that you can't modify the pointee
//p = 0; //it means you can't modify the pointer's value
return p;
}
int* const& get_reference_to_pointer() const //can't return a reference to non-const pointer
{
return p;
}
};

What is a reference in C?

I have just started C++ and have come across references and have not understood completely.
References , as i read is an alternative name for an object.Why use that instead of directly accessing the object as any operation on references is directly reflected on the object ...?
Why and when are they used ?
Is ist like a constant pointer that is referenced each time it is used ... ?
And , it says
double& dr = 1; ---- says it is an error (some lavalue needed)
const double& cdr = 1; ---- says it is ok.
i dont understand it properly..So please explain why it is so ...
Thank You...:)
Why use that instead of directly
accessing the object as any operation
on references is directly reflected on
the object ...?
C++ passes parameters by value, meaning if you have a function such as:
void foo(MyObject o) { ... }
By default C++ will make a copy of a MyObject, not directly use the object being passed in. So, one use of references is to ensure you are working on the same object:
void foo(MyObject &o) { ...}
Or, if you aren't modifying o:
void foo(const MyObject &o) { ... }
References are another way of what was originally in C code like this
void fubarSquare(int *x){
int y = *x;
*x = y * y;
}
// typical invocation
int z = 2;
fubarSquare(&z);
// now z is 4
with references in C++ it would be like this
void fubarSquareCpp(int& x){
x = x * x;
}
// typical invocation
int z = 2;
fubarSquareCpp(z);
// now z is 4
It's a neater syntactical way of using a call-by-reference parameter instead of using the C's notation asterisk/star to indicate a pointer and as a call-by-reference parameter...and modifying the parameter directly outside of the function...
Have a look at Bjarne Stoustrap's page here which covers how C++ is and also here on the technical faq here
A reference is basically a pointer that looks like an object. It is very very hard to get a NULL reference though you can go through hoops and create one.
With regards to your example, 1 is an rvalue or a result. It is just a temporary variable and can not be modified. Thus you can't take a non const reference to it. However you can take a const reference to it. This means you can't change the value of the reference.
Here is an example of creating a NULL reference. Don't do it!
int * x = (int *)NULL;
int & y = *x;
I agree with you. using references as just an alias name is not very useful.
It is more useful if you consider it as an immutable pointer. But not that useful in fact.
Practically, it is used to define clean interfaces. For example when you define:
int foo(const int& param);
You say that param is a read-only parameter in foo.
Do not forget that you MUST assign a value to a reference.
See the C++ faqlite on references for more
my2c
References improve the syntax, so no pointer dereference needed.
Assuming Base is a class that may be derived from:
void someFunction(Base b)
{
b.function();
// b is a copy of what was passed - probably performance issues
// possible unintended object slicing - you only get the Base part of it
// no virtual function call
// no changes to b visible outside the function
}
void someFunction(Base* b)
{
b->function();
// a shortcut for (*b).function();
// b is the same object that was passed to the function
// possible virtual call
// changes visible outside the function
}
void someFunction(Base& b)
{
b.function();
// b is the same object that was passed to the function
// possible virtual call
// changes visible outside the function
}
References are like constant pointers (NOT pointers to constants - i.e. you can change the object, but you can't change to what you're pointing). const reference is a reference through which you can do things that can be done on const object.
References are also good, because you can't have a null reference
Give the wikipedia article a good read through. To sum it up, references are more friendly version of pointers which are commonly used to pass objects as references into functions without worrying about a null pointer.
To explain the example:
Think of the number 1 represented as a variable. When compiled, this number is put into the global section of the memory which can be referenced by the program, but not modified.
So it is of type: const int
double &dr = 1 is trying to assign dr (a reference to a double) to the const int 1. Since 1 is a constant, the compiler will not allow you to make a non-constant reference to it.
In the second line:
const double &dr = 1 is trying to assign dr (a constant reference to a double) the const int 1. This works because the reference is also const and therefore can point to a const int.
EDIT
The const int is converted to a const double before assigned.
References are language entitities that represent another object they refer to. Nonconst references are lvalues, and must be initialized with an lvalue. They can be useful like this:
int& x=condition ? array[1] : array[2];
int& y=condition ? array[0] : array[3];
x+=y;
y=0;
When used as a function parameter, they tell the caller he has to pass an lvalue that might be written to by the function:
void set1(int& x) { x=1; }
int foo;
set1(foo); // ok, foo is 1
set1(foo+1); // not OK, not lvalue
Const references, on the other hand, can be bound to rvalues. In function parameters, they are usually used to avoid excessive copies:
void niceness(std::string s); // the string would be copied by its copy-ctor
void niceness(const std::string& s); // the caller's string would be used
Note that this may or may not yield faster code.
When const-references are used in normal code, they can bind rvalues, too, and as a special rule, they extend the lifetime of the object they are bound to. This is what you saw in your code:
const double& d=1; // OK, bind a rvalue to a const-ref
double& d=1; // Bad, need lvalue
All references are polymorphic, like pointers:
class A { virtual void f(); }
class B : public A { void f(); }
B b;
A& ar=b;
ar.f(); // calls B::f()
and all references are aliases like pointers:
int f(int& a, const int& b)
{
a=1;
return b;
}
int x;
f(x, 42); // ==42, foo=1
x=42;
f(x, x); // ==1 (not 42), foo=1
double& dr = 1; // 1.0 would be more clear
Is invalid because 1 is viewed to be of type const double so if you want a reference to that variable you need to have a reference to a const double so
const double& dr = 1.0;
Is correct.
Utility of references is most visible in the context of passing parameters to functions.
I.e,
int a;
func definition: void foo (int& param) {param = 1;}
func call: foo(a);
The way as 'param' aliases 'a' is clean and its intention is easily understood by a reader of this code as well as compiler that may optimize away when inlining any additional memory allocation needed for the reference.
Passing a reference to a function and then having the function use the reference is almost like passing a pointer to the function and then having the function dereference the pointer. In many cases, the machine-code implementation will be identical. There are some differences, though, especially in the case of functions that get expanded inline. If a variable is passed by reference to an inline function, the compiler will often be able to substitute the variable itself--even if stored in a machine register--when expanding the function. By contrast, if one takes the address of a variable and passes that as a pointer to a function which then dereferences it, the compiler is less likely to figure out that optimization unless it determines not only that--at least for one particular expansion of the function--the pointer will always point to that variable, but also that the pointer will not be used anywhere else (if the pointer was used elsewhere, the variable could not be kept in a register).

Difference of function argument as (const int &) and (int & a) in C++

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!!!)???
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
}
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.
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.
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.
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.
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'
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