passing object by reference in C++ - c++

The usual way to pass a variable by reference in C++(also C) is as follows:
void _someFunction(dataType *name){ // dataType e.g int,char,float etc.
/****
definition
*/
}
int main(){
dataType v;
_somefunction(&v); //address of variable v being passed
return 0;
}
But to my surprise, I noticed when passing an object by reference the name of object itself serves the purpose(no & symbol required) and that during declaration/definition of function no * symbol is required before the argument.
The following example should make it clear:
// this
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme (CDummy& param); //why not (CDummy* param);
};
int CDummy::isitme (CDummy& param)
{
if (&param == this) return true;
else return false;
}
int main () {
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) ) //why not isitme(&a)
cout << "yes, &a is b";
return 0;
}
I have problem understanding why is this special treatment done with class . Even structures which are almost like a class are not used this way. Is object name treated as address as in case of arrays?

What seems to be confusing you is the fact that functions that are declared to be pass-by-reference (using the &) aren't called using actual addresses, i.e. &a.
The simple answer is that declaring a function as pass-by-reference:
void foo(int& x);
is all we need. It's then passed by reference automatically.
You now call this function like so:
int y = 5;
foo(y);
and y will be passed by reference.
You could also do it like this (but why would you? The mantra is: Use references when possible, pointers when needed) :
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme (CDummy* param);
};
int CDummy::isitme (CDummy* param)
{
if (param == this) return true;
else return false;
}
int main () {
CDummy a;
CDummy* b = &a; // assigning address of a to b
if ( b->isitme(&a) ) // Called with &a (address of a) instead of a
cout << "yes, &a is b";
return 0;
}
Output:
yes, &a is b

A reference is really a pointer with enough sugar to make it taste nice... ;)
But it also uses a different syntax to pointers, which makes it a bit easier to use references than pointers. Because of this, we don't need & when calling the function that takes the pointer - the compiler deals with that for you. And you don't need * to get the content of a reference.
To call a reference an alias is a pretty accurate description - it is "another name for the same thing". So when a is passed as a reference, we're really passing a, not a copy of a - it is done (internally) by passing the address of a, but you don't need to worry about how that works [unless you are writing your own compiler, but then there are lots of other fun things you need to know when writing your own compiler, that you don't need to worry about when you are just programming].
Note that references work the same way for int or a class type.

Ok, well it seems that you are confusing pass-by-reference with pass-by-value. Also, C and C++ are different languages. C doesn't support pass-by-reference.
Here are two C++ examples of pass by value:
// ex.1
int add(int a, int b)
{
return a + b;
}
// ex.2
void add(int a, int b, int *result)
{
*result = a + b;
}
void main()
{
int result = 0;
// ex.1
result = add(2,2); // result will be 4 after call
// ex.2
add(2,3,&result); // result will be 5 after call
}
When ex.1 is called, the constants 2 and 2 are passed into the function by making local copies of them on the stack. When the function returns, the stack is popped off and anything passed to the function on the stack is effectively gone.
The same thing happens in ex.2, except this time, a pointer to an int variable is also passed on the stack. The function uses this pointer (which is simply a memory address) to dereference and change the value at that memory address in order to "return" the result. Since the function needs a memory address as a parameter, then we must supply it with one, which we do by using the & "address-of" operator on the variable result.
Here are two C++ examples of pass-by-reference:
// ex.3
int add(int &a, int &b)
{
return a+b;
}
// ex.4
void add(int &a, int &b, int &result)
{
result = a + b;
}
void main()
{
int result = 0;
// ex.3
result = add(2,2); // result = 2 after call
// ex.4
add(2,3,result); // result = 5 after call
}
Both of these functions have the same end result as the first two examples, but the difference is in how they are called, and how the compiler handles them.
First, lets clear up how pass-by-reference works. In pass-by-reference, generally the compiler implementation will use a "pointer" variable in the final executable in order to access the referenced variable, (or so seems to be the consensus) but this doesn't have to be true. Technically, the compiler can simply substitute the referenced variable's memory address directly, and I suspect this to be more true than generally believed. So, when using a reference, it could actually produce a more efficient executable, even if only slightly.
Next, obviously the way a function is called when using pass-by-reference is no different than pass-by-value, and the effect is that you have direct access to the original variables within the function. This has the result of encapsulation by hiding the implementation details from the caller. The downside is that you cannot change the passed in parameters without also changing the original variables outside of the function. In functions where you want the performance improvement from not having to copy large objects, but you don't want to modify the original object, then prefix the reference parameters with const.
Lastly, you cannot change a reference after it has been made, unlike a pointer variable, and they must be initialized upon creation.
Hope I covered everything, and that it was all understandable.

Passing by reference in the above case is just an alias for the actual object.
You'll be referring to the actual object just with a different name.
There are many advantages which references offer compared to pointer references.

One thing that I have to add is that there is no reference in C.
Secondly, this is the language syntax convention.
& - is an address operator but it also mean a reference - all depends on usa case
If there was some "reference" keyword instead of & you could write
int CDummy::isitme (reference CDummy param)
but this is C++ and we should accept it advantages and disadvantages...

Related

Transferring variables with object reference. With or without &?

#include <iostream>
class class1
{
public:int number = 2;
};
class class2
{
public:
void method(class1 &obj)
{
obj.number;
std::cout << obj.number;
}
};
int main()
{
class1 c1;
class2 c2;
c2.method(c1);
}
What is the difference between running the void method(class1 &obj) with or without &?
Does it change use of memory?
I've heard it's nice to use & so you don't get a NullReferenceException.
I can still access the variable without &, so should i use & in this dumb example?
To make it very simple,
Pass by value means the actual value is passed on. Thus you need to copy this value to a variable to use it.
void method(class1 obj)
Pass by reference means a number (called an address) is passed on which defines where the value is stored.
The address is passed and then no copy is done and the actual object is modified.
void method(class1 &obj)
Pass-by-references is considered to be more efficient than pass-by-value, because it does not copy the arguments to a new variable of the same type (as it uses the actual object).
Also beware as pass-by-value does not modify the real object (only the copy). A great example to look at for instance is the ̀swap two variables`
as follows:
void swap(int a, int b)
{
int t;
t = b;
b = a;
a = t;
}
If you call by value in a main function using `swap(x,y)̀, the inital value (before the call) and the final value (after the call) does not swap.
However, if you define the function instead by reference void swap(int& a, int& b) (nothing changes in the body of the function), you will see that calling swap(x,y), will indeed swap the two variables as the operation.

C++: what is the advantage of references in this case?

I have two pieces of code:
int f1(int b)
{
return b;
}
int & f2(int b)
{
return b;
}
What is the difference between these functions? I know that the second one returns a reference, but since I can use both functions in the same way, what's the difference?
Edit: Is this function better?
int && f2(int b)
{
return b;
}
And when should I use functions which return references?
Edit2: Then when should I use functions which return Rvalue references?
Consider a simple class that wraps an array solely for the purpose of providing an example of what the OP can do with a returned reference.
class example
{
private:
int array[]= {1,2,3,4,5,6,7,8,9,0};
public:
int get(int index)
{
return array[index];
}
int & get2(int index)
{
return array[index];
}
}
Now we have an example that will not go into the badlands of undefined behaviour and can show you the power of this fully armed and operational reference.
Say we have
example x;
We can call either get function to retrieve a value
int val1 = x.get(1);
int val2 = x.get2(2)
but we can also
x.get2(3) = 30;
because get2 returns a reference we can assign to it and make the assignment stick.
This is invaluable should you want to add an index operator to example
int & operator[](int index)
{
return array[index];
}
because it allows the expected array behaviour
int val = x[5];
x[6] = 10;
EDIT
Tony D brings up another important feature. Returning a reference returns by reference. In addition to allowing modification of the returned object, this does not make a copy and saves whatever effort would have been consumed by making a copy. For the example case of integers this is moot. The cost of passing an integer and a reference to an integer will either be the same or so close that it shouldn't matter. This is not true of a larger, more complex object that could take a significant amount of effort to copy or an object that cannot or should not be copied.
BigFreakingObject & getBigFreakingObject();
will allow the caller to operate on a BigFreakingObject without incurring the costs of duplicating it. This hands over the keys to the kingdom however and allows the caller to do to BigFreakingObject whatever BigFreakingObject's permissions will allow, and this may conflict with the requirements of BigFreakingObject's owner.
Declaring the reference as const with
const BigFreakingObject & getBigFreakingObject();
or
BigFreakingObject const & getBigFreakingObject();
will provide a reference to a BigFreakingObject but not allow the caller to modify its state, protecting the owner of BigFreakingObject from any unpleasant surprises.
For more details on this, read up on Const Correctness.
int f1(int b) {
return b;
}
returns the integer b.
int & f2(int b) {
return b;
}
returns a reference to an integer b that was destroyed when the function returned. In other words, you passed b by value to the function, which means b has an address in the stack frame of the function. Once the function returns, anything in that function's stack frame, including the b that you returned a reference to, no longer exists. So, you have no idea what the reference actually refers to, so you can't use it.
Edit: Your edited function is not better. This would be more correct:
int& f2(int& b) {
return b;
}
Unless you have a situation like the example #user4581301 gave, you should never return a reference to an object created within the function you are returning from, for the reasons described above!
If you want to pass an object to a function, and have the function do something to that object without ever making a copy of the object, do the following:
void f2(int& b) {
... do stuff to b
}
In...
int & f2(int b)
{
return b;
}
...the argument b is an automatic (stack-hosted) copy of the caller-provided value: when f2 returns that stack space is reclaimed. When returning an int&, you're passing back a reference to f2's b variable even as it's memory is made available for reuse. If you make any attempt to access the value using the returned reference, you have undefined behaviour.

Why would you pass an object by pointer and not by reference? [duplicate]

I am new to C++ programming, but I have experience in Java. I need guidance on how to pass objects to functions in C++.
Do I need to pass pointers, references, or non-pointer and non-reference values? I remember in Java there are no such issues since we pass just the variable that holds reference to the objects.
It would be great if you could also explain where to use each of those options.
Rules of thumb for C++11:
Pass by value, except when
you do not need ownership of the object and a simple alias will do, in which case you pass by const reference,
you must mutate the object, in which case, use pass by a non-const lvalue reference,
you pass objects of derived classes as base classes, in which case you need to pass by reference. (Use the previous rules to determine whether to pass by const reference or not.)
Passing by pointer is virtually never advised. Optional parameters are best expressed as a std::optional (boost::optional for older std libs), and aliasing is done fine by reference.
C++11's move semantics make passing and returning by value much more attractive even for complex objects.
Rules of thumb for C++03:
Pass arguments by const reference, except when
they are to be changed inside the function and such changes should be reflected outside, in which case you pass by non-const reference
the function should be callable without any argument, in which case you pass by pointer, so that users can pass NULL/0/nullptr instead; apply the previous rule to determine whether you should pass by a pointer to a const argument
they are of built-in types, which can be passed by copy
they are to be changed inside the function and such changes should not be reflected outside, in which case you can pass by copy (an alternative would be to pass according to the previous rules and make a copy inside of the function)
(here, "pass by value" is called "pass by copy", because passing by value always creates a copy in C++03)
There's more to this, but these few beginner's rules will get you quite far.
There are some differences in calling conventions in C++ and Java. In C++ there are technically speaking only two conventions: pass-by-value and pass-by-reference, with some literature including a third pass-by-pointer convention (that is actually pass-by-value of a pointer type). On top of that, you can add const-ness to the type of the argument, enhancing the semantics.
Pass by reference
Passing by reference means that the function will conceptually receive your object instance and not a copy of it. The reference is conceptually an alias to the object that was used in the calling context, and cannot be null. All operations performed inside the function apply to the object outside the function. This convention is not available in Java or C.
Pass by value (and pass-by-pointer)
The compiler will generate a copy of the object in the calling context and use that copy inside the function. All operations performed inside the function are done to the copy, not the external element. This is the convention for primitive types in Java.
An special version of it is passing a pointer (address-of the object) into a function. The function receives the pointer, and any and all operations applied to the pointer itself are applied to the copy (pointer), on the other hand, operations applied to the dereferenced pointer will apply to the object instance at that memory location, so the function can have side effects. The effect of using pass-by-value of a pointer to the object will allow the internal function to modify external values, as with pass-by-reference and will also allow for optional values (pass a null pointer).
This is the convention used in C when a function needs to modify an external variable, and the convention used in Java with reference types: the reference is copied, but the referred object is the same: changes to the reference/pointer are not visible outside the function, but changes to the pointed memory are.
Adding const to the equation
In C++ you can assign constant-ness to objects when defining variables, pointers and references at different levels. You can declare a variable to be constant, you can declare a reference to a constant instance, and you can define all pointers to constant objects, constant pointers to mutable objects and constant pointers to constant elements. Conversely in Java you can only define one level of constant-ness (final keyword): that of the variable (instance for primitive types, reference for reference types), but you cannot define a reference to an immutable element (unless the class itself is immutable).
This is extensively used in C++ calling conventions. When the objects are small you can pass the object by value. The compiler will generate a copy, but that copy is not an expensive operation. For any other type, if the function will not change the object, you can pass a reference to a constant instance (usually called constant reference) of the type. This will not copy the object, but pass it into the function. But at the same time the compiler will guarantee that the object is not changed inside the function.
Rules of thumb
This are some basic rules to follow:
Prefer pass-by-value for primitive types
Prefer pass-by-reference with references to constant for other types
If the function needs to modify the argument use pass-by-reference
If the argument is optional, use pass-by-pointer (to constant if the optional value should not be modified)
There are other small deviations from these rules, the first of which is handling ownership of an object. When an object is dynamically allocated with new, it must be deallocated with delete (or the [] versions thereof). The object or function that is responsible for the destruction of the object is considered the owner of the resource. When a dynamically allocated object is created in a piece of code, but the ownership is transfered to a different element it is usually done with pass-by-pointer semantics, or if possible with smart pointers.
Side note
It is important to insist in the importance of the difference between C++ and Java references. In C++ references are conceptually the instance of the object, not an accessor to it. The simplest example is implementing a swap function:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
The swap function above changes both its arguments through the use of references. The closest code in Java:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
The Java version of the code will modify the copies of the references internally, but will not modify the actual objects externally. Java references are C pointers without pointer arithmetic that get passed by value into functions.
There are several cases to consider.
Parameter modified ("out" and "in/out" parameters)
void modifies(T &param);
// vs
void modifies(T *param);
This case is mostly about style: do you want the code to look like call(obj) or call(&obj)? However, there are two points where the difference matters: the optional case, below, and you want to use a reference when overloading operators.
...and optional
void modifies(T *param=0); // default value optional, too
// vs
void modifies();
void modifies(T &param);
Parameter not modified
void uses(T const &param);
// vs
void uses(T param);
This is the interesting case. The rule of thumb is "cheap to copy" types are passed by value — these are generally small types (but not always) — while others are passed by const ref. However, if you need to make a copy within your function regardless, you should pass by value. (Yes, this exposes a bit of implementation detail. C'est le C++.)
...and optional
void uses(T const *param=0); // default value optional, too
// vs
void uses();
void uses(T const &param); // or optional(T param)
There's the least difference here between all situations, so choose whichever makes your life easiest.
Const by value is an implementation detail
void f(T);
void f(T const);
These declarations are actually the exact same function! When passing by value, const is purely an implementation detail. Try it out:
void f(int);
void f(int const) { /* implements above function, not an overload */ }
typedef void NC(int); // typedefing function types
typedef void C(int const);
NC *nc = &f; // nc is a function pointer
C *c = nc; // C and NC are identical types
Pass by value:
void func (vector v)
Pass variables by value when the function needs complete isolation from the environment i.e. to prevent the function from modifying the original variable as well as to prevent other threads from modifying its value while the function is being executed.
The downside is the CPU cycles and extra memory spent to copy the object.
Pass by const reference:
void func (const vector& v);
This form emulates pass-by-value behavior while removing the copying overhead. The function gets read access to the original object, but cannot modify its value.
The downside is thread safety: any change made to the original object by another thread will show up inside the function while it's still executing.
Pass by non-const reference:
void func (vector& v)
Use this when the function has to write back some value to the variable, which will ultimately get used by the caller.
Just like the const reference case, this is not thread-safe.
Pass by const pointer:
void func (const vector* vp);
Functionally same as pass by const-reference except for the different syntax, plus the fact that the calling function can pass NULL pointer to indicate it has no valid data to pass.
Not thread-safe.
Pass by non-const pointer:
void func (vector* vp);
Similar to non-const reference. The caller typically sets the variable to NULL when the function is not supposed to write back a value. This convention is seen in many glibc APIs. Example:
void func (string* str, /* ... */) {
if (str != NULL) {
*str = some_value; // assign to *str only if it's non-null
}
}
Just like all pass by reference/pointer, not thread-safe.
Since no one mentioned I am adding on it, When you pass a object to a function in c++ the default copy constructor of the object is called if you dont have one which creates a clone of the object and then pass it to the method, so when you change the object values that will reflect on the copy of the object instead of the original object, that is the problem in c++, So if you make all the class attributes to be pointers, then the copy constructors will copy the addresses of the pointer attributes , so when the method invocations on the object which manipulates the values stored in pointer attributes addresses, the changes also reflect in the original object which is passed as a parameter, so this can behave same a Java but dont forget that all your class attributes must be pointers, also you should change the values of pointers, will be much clear with code explanation.
Class CPlusPlusJavaFunctionality {
public:
CPlusPlusJavaFunctionality(){
attribute = new int;
*attribute = value;
}
void setValue(int value){
*attribute = value;
}
void getValue(){
return *attribute;
}
~ CPlusPlusJavaFuncitonality(){
delete(attribute);
}
private:
int *attribute;
}
void changeObjectAttribute(CPlusPlusJavaFunctionality obj, int value){
int* prt = obj.attribute;
*ptr = value;
}
int main(){
CPlusPlusJavaFunctionality obj;
obj.setValue(10);
cout<< obj.getValue(); //output: 10
changeObjectAttribute(obj, 15);
cout<< obj.getValue(); //output: 15
}
But this is not good idea as you will be ending up writing lot of code involving with pointers, which are prone for memory leaks and do not forget to call destructors. And to avoid this c++ have copy constructors where you will create new memory when the objects containing pointers are passed to function arguments which will stop manipulating other objects data, Java does pass by value and value is reference, so it do not require copy constructors.
Do I need to pass pointers, references, or non-pointer and non-reference values?
This is a question that matters when writing a function and choosing the types of the parameters it takes. That choice will affect how the function is called and it depends on a few things.
The simplest option is to pass objects by value. This basically creates a copy of the object in the function, which has many advantages. But sometimes copying is costly, in which case a constant reference, const&, is usually best. And sometimes you need your object to be changed by the function. Then a non-constant reference, &, is needed.
For guidance on the choice of parameter types, see the Functions section of the C++ Core Guidelines, starting with F.15. As a general rule, try to avoid raw pointers, *.
There are three methods of passing an object to a function as a parameter:
Pass by reference
pass by value
adding constant in parameter
Go through the following example:
class Sample
{
public:
int *ptr;
int mVar;
Sample(int i)
{
mVar = 4;
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value of the pointer is " << *ptr << endl
<< "The value of the variable is " << mVar;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
char ch;
cin >> ch;
}
Output:
Say i am in someFunc
The value of the pointer is -17891602
The value of the variable is 4
The following are the ways to pass a arguments/parameters to function in C++.
1. by value.
// passing parameters by value . . .
void foo(int x)
{
x = 6;
}
2. by reference.
// passing parameters by reference . . .
void foo(const int &x) // x is a const reference
{
x = 6;
}
// passing parameters by const reference . . .
void foo(const int &x) // x is a const reference
{
x = 6; // compile error: a const reference cannot have its value changed!
}
3. by object.
class abc
{
display()
{
cout<<"Class abc";
}
}
// pass object by value
void show(abc S)
{
cout<<S.display();
}
// pass object by reference
void show(abc& S)
{
cout<<S.display();
}

Does this code subvert the C++ type system?

I understand that having a const method in C++ means that an object is read-only through that method, but that it may still change otherwise.
However, this code apparently changes an object through a const reference (i.e. through a const method).
Is this code legal in C++?
If so: Is it breaking the const-ness of the type system? Why/why not?
If not: Why not?
Note 1: I have edited the example a bit, so answers might be referring to older examples.
Edit 2: Apparently you don't even need C++11, so I removed that dependency.
#include <iostream>
using namespace std;
struct DoBadThings { int *p; void oops() const { ++*p; } };
struct BreakConst
{
int n;
DoBadThings bad;
BreakConst() { n = 0; bad.p = &n; }
void oops() const { bad.oops(); } // can't change itself... or can it?
};
int main()
{
const BreakConst bc;
cout << bc.n << endl; // 0
bc.oops(); // O:)
cout << bc.n << endl; // 1
return 0;
}
Update:
I have migrated the lambda to the constructor's initialization list, since doing so allows me to subsequently say const BreakConst bc;, which -- because bc itself is now const (instead of merely the pointer) -- would seem to imply (by Stroustrup) that modifying bc in any way after construction should result in undefined behavior, even though the constructor and the caller would have no way of knowing this without seeing each others' definitions.
The oops() method isn't allowed to change the constness of the object. Furthermore it doesn't do it. Its your anonymous function that does it. This anonymous function isn't in the context of the object, but in the context of the main() method which is allowed to modify the object.
Your anonymous function doesn't change the this pointer of oops() (which is defined as const and therefore can't be changed) and also in no way derives some non-const variable from this this-pointer. Itself doesn't have any this-pointer. It just ignores the this-pointer and changes the bc variable of the main context (which is kind of passed as parameter to your closure). This variable is not const and therefore can be changed. You could also pass any anonymous function changing a completely unrelated object. This function doesn't know, that its changing the object that stores it.
If you would declare it as
const BreakConst bc = ...
then the main function also would handle it as const object and couldn't change it.
Edit:
In other words: The const attribute is bound to the concrete l-value (reference) accessing the object. It's not bound to the object itself.
You code is correct, because you don't use the const reference to modify the object. The lambda function uses completely different reference, which just happen to be pointing to the same object.
In the general, such cases does not subvert the type system, because the type system in C++ does not formally guarantee, that you can't modify the const object or the const reference. However modification of the const object is the undefined behaviour.
From [7.1.6.1] The cv-qualifiers:
A pointer or reference to a cv-qualified type need not actually point
or refer to a cv-qualified object, but it is treated as if it does; a
const-qualified access path cannot be used to modify an object even if
the object referenced is a non-const object and can be modified through
some other access path.
Except that any class member declared mutable (7.1.1) can be modified,
any attempt to modify a const object during its lifetime (3.8) results
in undefined behavior.
I already saw something similar. Basically you invoke a cost function that invoke something else that modifies the object without knowing it.
Consider this as well:
#include <iostream>
using namespace std;
class B;
class A
{
friend class B;
B* pb;
int val;
public:
A(B& b);
void callinc() const;
friend ostream& operator<<(ostream& s, const A& a)
{ return s << "A value is " << a.val; }
};
class B
{
friend class A;
A* pa;
public:
void incval() const { ++pa->val; }
};
inline A::A(B& b) :pb(&b), val() { pb->pa = this; }
inline void A::callinc() const { pb->incval(); }
int main()
{
B b;
const A a(b); // EDIT: WAS `A a(b)`
cout << a << endl;
a.callinc();
cout << a << endl;
}
This is not C++11, but does the same:
The point is that const is not transitive.
callinc() doesn't change itself a and incval doesn't change b.
Note that in main you can even declare const A a(b); instead of A a(b); and everything compile the same.
This works from decades, and in your sample you're just doing the same: simply you replaced class B with a lambda.
EDIT
Changed the main() to reflect the comment.
The issue is one of logical const versus bitwise const. The compiler
doesn't know anything about the logical meaning of your program, and
only enforces bitwise const. It's up to you to implement logical const.
This means that in cases like you show, if the pointed to memory is
logically part of the object, you should refrain from modifying it in a
const function, even if the compiler will let you (since it isn't part
of the bitwise image of the object). This may also mean that if part of
the bitwise image of the object isn't part of the logical value of the
object (e.g. an embedded reference count, or cached values), you make it
mutable, or even cast away const, in cases where you modify it without
modifying the logical value of the object.
The const feature merely helps against accidental misuse. It is not designed to prevent dedicated software hacking. It is the same as private and protected membership, someone could always take the address of the object and increment along the memory to access class internals, there is no way to stop it.
So, yes you can get around const. If nothing else you can simply change the object at the memory level but this does not mean const is broken.

Which are the implications of return a value as constant, reference and constant reference in C++?

I'm learning C++ and I'm still confused about this. What are the implications of return a value as constant, reference and constant reference in C++ ? For example:
const int exampleOne();
int& exampleTwo();
const int& exampleThree();
Here's the lowdown on all your cases:
• Return by reference: The function call can be used as the left hand side of an assignment. e.g. using operator overloading, if you have operator[] overloaded, you can say something like
a[i] = 7;
(when returning by reference you need to ensure that the object you return is available after the return: you should not return a reference to a local or a temporary)
• Return as constant value: Prevents the function from being used on the left side of an assignment expression. Consider the overloaded operator+. One could write something like:
a + b = c; // This isn't right
Having the return type of operator+ as "const SomeType" allows the return by value and at the same time prevents the expression from being used on the left side of an assignment.
Return as constant value also allows one to prevent typos like these:
if (someFunction() = 2)
when you meant
if (someFunction() == 2)
If someFunction() is declared as
const int someFunction()
then the if() typo above would be caught by the compiler.
• Return as constant reference: This function call cannot appear on the left hand side of an assignment, and you want to avoid making a copy (returning by value). E.g. let's say we have a class Student and we'd like to provide an accessor id() to get the ID of the student:
class Student
{
std::string id_;
public:
const std::string& id() const;
};
const std::string& Student::id()
{
return id_;
}
Consider the id() accessor. This should be declared const to guarantee that the id() member function will not modify the state of the object. Now, consider the return type. If the return type were string& then one could write something like:
Student s;
s.id() = "newId";
which isn't what we want.
We could have returned by value, but in this case returning by reference is more efficient. Making the return type a const string& additionally prevents the id from being modified.
The basic thing to understand is that returning by value will create a new copy of your object. Returning by reference will return a reference to an existing object. NOTE: Just like pointers, you CAN have dangling references. So, don't create an object in a function and return a reference to the object -- it will be destroyed when the function returns, and it will return a dangling reference.
Return by value:
When you have POD (Plain Old Data)
When you want to return a copy of an object
Return by reference:
When you have a performance reason to avoid a copy of the object you are returning, and you understand the lifetime of the object
When you must return a particular instance of an object, and you understand the lifetime of the object
Const / Constant references help you enforce the contracts of your code, and help your users' compilers find usage errors. They do not affect performance.
Returning a constant value isn't a very common idiom, since you're returning a new thing anyway that only the caller can have, so it's not common to have a case where they can't modify it. In your example, you don't know what they're going to do with it, so why should you stop them from modifying it?
Note that in C++ if you don't say that something is a reference or pointer, it's a value so you'll create a new copy of it rather than modifying the original object. This might not be totally obvious if you're coming from other languages that use references by default.
Returning a reference or const reference means that it's actually another object elsewhere, so any modifications to it will affect that other object. A common idiom there might be exposing a private member of a class.
const means that whatever it is can't be modified, so if you return a const reference you can't call any non-const methods on it or modify any data members.
Return by reference.
You can return a reference to some value, such as a class member. That way, you don't create copies. However, you shouldn't return references to values in a stack, as that results in undefined behaviour.
#include <iostream>
using namespace std;
class A{
private: int a;
public:
A(int num):a(num){}
//a to the power of 4.
int& operate(){
this->a*=this->a;
this->a*=this->a;
return this->a;
}
//return constant copy of a.
const int constA(){return this->a;}
//return copy of a.
int getA(){return this->a;}
};
int main(){
A obj(3);
cout <<"a "<<obj.getA()<<endl;
int& b=obj.operate(); //obj.operate() returns a reference!
cout<<"a^4 "<<obj.getA()<<endl;
b++;
cout<<"modified by b: "<<obj.getA()<<endl;
return 0;
}
b and obj.a "point" to the same value, so modifying b modifies the value of obj.a.
$./a.out
a 3
a^4 81
modified by b: 82
Return a const value.
On the other hand, returning a const value indicates that said value cannot be modified. It should be remarked that the returned value is a copy.:
For example,
constA()++;
would result in a compilation error, since the copy returned by constA() is constant. But this is just a copy, it doesn't imply that A::a is constant.
Return a const reference.
This is similiar to returning a const value, except that no copy is return, but a reference to the actual member. However, it cant be modified.
const int& refA(){return this->a;}
const int& b = obj.refA();
b++;
will result in a compilation error.
const int exampleOne();
Returns a const copy of some int. That is, you create a new int which may not be modified. This isn't really useful in most cases because you're creating a copy anyway, so you typically don't care if it gets modified. So why not just return a regular int?
It may make a difference for more complex types, where modifying them may have undesirable sideeffects though. (Conceptually, let's say a function returns an object representing a file handle. If that handle is const, the file is read-only, otherwise it can be modified. Then in some cases it makes sense for a function to return a const value. But in general, returning a const value is uncommon.
int& exampleTwo();
This one returns a reference to an int. This does not affect the lifetime of that value though, so this can lead to undefined behavior in a case such as this:
int& exampleTwo() {
int x = 42;
return x;
}
we're returning a reference to a value that no longer exists. The compiler may warn you about this, but it'll probably compile anyway. But it's meaningless and will cause funky crashes sooner or later. This is used often in other cases though. If the function had been a class member, it could return a reference to a member variable, whose lifetime would last until the object goes out of scope, which means function return value is still valid when the function returns.
const int& exampleThree();
Is mostly the same as above, returning a reference to some value without taking ownership of it or affecting its lifetime. The main difference is that now you're returning a reference to a const (immutable) object. Unlike the first case, this is more often useful, since we're no longer dealing with a copy that no one else knows about, and so modifications may be visible to other parts of the code. (you may have an object that's non-const where it's defined, and a function that allows other parts of the code to get access to it as const, by returning a const reference to it.
Your first case:
const int exampleOne();
With simple types like int, this is almost never what you want, because the const is pointless. Return by value implies a copy, and you can assign to a non-const object freely:
int a = exampleOne(); // perfectly valid.
When I see this, it's usually because whoever wrote the code was trying to be const-correct, which is laudable, but didn't quite understand the implications of what they were writing. However, there are cases with overloaded operators and custom types where it can make a difference.
Some compilers (newer GCCs, Metrowerks, etc) warn on behavior like this with simple types, so it should be avoided.
I think that your question is actually two questions:
What are the implications of returning a const.
What are the implications of returning a reference.
To give you a better answer, I will explain a little more about both concepts.
Regarding the const keyword
The const keyword means that the object cannot be modified through that variable, for instance:
MyObject *o1 = new MyObject;
const MyObject *o2 = o1;
o1->set(...); // Will work and will change the instance variables.
o2->set(...); // Won't compile.
Now, the const keyword can be used in three different contexts:
Assuring the caller of a method that you won't modify the object
For example:
void func(const MyObject &o);
void func(const MyObject *o);
In both cases, any modification made to the object will remain outside the function scope, that's why using the keyword const I assure the caller that I won't be modifying it's instance variables.
Assuring the compiler that a specific method do not mutate the object
If you have a class and some methods that "gets" or "obtains" information from the instance variables without modifying them, then I should be able to use them even if the const keyword is used. For example:
class MyObject
{
...
public:
void setValue(int);
int getValue() const; // The const at the end is the key
};
void funct(const MyObject &o)
{
int val = o.getValue(); // Will compile.
a.setValue(val); // Won't compile.
}
Finally, (your case) returning a const value
This means that the returned object cannot be modified or mutated directly. For example:
const MyObject func();
void func2()
{
int val = func()->getValue(); // Will compile.
func()->setValue(val); // Won't compile.
MyObject o1 = func(); // Won't compile.
MyObject o2 = const_cast<MyObject>(func()); // Will compile.
}
More information about the const keyword: C++ Faq Lite - Const Correctness
Regarding references
Returning or receiving a reference means that the object will not be duplicated. This means that any change made to the value itself will be reflected outside the function scope. For example:
void swap(int &x, int &y)
{
int z = x;
x = y;
y = z;
}
int a = 2; b = 3;
swap(a, b); // a IS THE SAME AS x inside the swap function
So, returning a reference value means that the value can be changed, for instance:
class Foo
{
public:
...
int &val() { return m_val; }
private:
int m_val;
};
Foo f;
f.val() = 4; // Will change m_val.
More information about references: C++ Faq Lite - Reference and value semantics
Now, answering your questions
const int exampleOne();
Means the object returned cannot change through the variable. It's more useful when returning objects.
int& exampleTwo();
Means the object returned is the same as the one inside the function and any change made to that object will be reflected inside the function.
const int& exampleThree();
Means the object returned is the same as the one inside the function and cannot be modified through that variable.
Never thought, that we can return a const value by reference and I don't see the value in doing so..
But, it makes sense if you try to pass a value to a function like this
void func(const int& a);
This has the advantage of telling the compiler to not make a copy of the variable a in memory (which is done when you pass an argument by value and not by reference). The const is here in order to avoid the variable a to be modified.