Returning references from a C++ methods - c++

Dear friends, i'm concerned if i'm making a bad use of references in C++
In the following method GCC complains warning "reference to local variable ‘me’ returned"
MatrizEsparsa& MatrizEsparsa::operator+(MatrizEsparsa& outra){
MatrizEsparsa me(outra.linhas(),outra.colunas());
return me;
}
But, with the following changes the warning disappears:
MatrizEsparsa& MatrizEsparsa::operator+(MatrizEsparsa& outra){
MatrizEsparsa me(outra.linhas(),outra.colunas());
MatrizEsparsa &ref = me;
return ref;
}
Is the former method ( returning the 'ref' variable ) correct\acceptable ?

No. ref still refers to me which will be destroyed at the end of the call.
You should return a copy of your result (not prefixed by &).
MatrizEsparsa MatrizEsparsa::operator+(const MatrizEsparsa& outra) const {
return MatrizEsparsa(outra.linhas(),outra.colunas());
}
I also added two const specifiers (to the parameter and to the method) since I doubt outra or the calling instance need to be modified in this case. (I could be wrong, but then your operator+ would have a weird semantic)
By doing what you did, you just made the code more complex. The compiler probably was confused and couldn't warn you about your possible mistake.
Usually, when you have to use clever tricks to do simple things, it means something is wrong.

I think you're mistaking your operators.
There are 2:
struct Foo
{
Foo& operator+=(Foo const&);
Foo operator+(Foo const&) const;
};
As you notice, the first returns a reference to itself, the second does not.
Also, in general, the second should be written as a free function.
Foo operator+(Foo const&, Foo const&);
This can be automated, because it's cumbersome, using Boost.Operators:
struct Foo: boost::addable<Foo>
{
Foo& operator+=(Foo const& rhs)
{
// add
return *this;
}
};
The little boost::addable magic will automatically generate the + implementation based on Foo::operator+=.

It is not acceptable. It is actually the same problem: returning a non-const reference to an local object that will be destroyed after returning the method.

No, you must return a value here, ideally a const value. See Effective C++, Item 21.
I suggest the following interface:
const MatrizEsparsa operator+(const MatrizEsparsa& left, const MatrizEsparsa& right);
Note that everything is either a const reference or a const value. Returning a const value is not as important as returning a value or declaring the parameters as const references, but the arguments of Scott Meyers have convinced me, although no one follows them.

You can't return the reference since the object you are referencing will get destroyed outside of your control. Either put "me" as a member variable of MatrizEsparsa so that it will persist after execution of the function else return a pointer, or a boost smart_ptr, that points to the object.
Seeing as this is a + operator though, you probably want to return a value rather than a reference to a variable internal to the function.

Related

Returning const reference for vectors [duplicate]

What is the best practice for a C++ getter method which is supposed to return a non trivial type, but a member which is of type class, or struct.
Return by value, such as: MyType MyClass::getMyType() { return mMyType; }
Return by const reference: const MyType& MyClass::getMyType() { return mMyType; }
Return by address: MyType* MyClass::getMyType() { return &mMyType; }
where
class MyType { /* ... */ };
class MyClass
{
private:
MyType mMyType;
}
I specifically worry about the following usages of this method. Can you please elaborate in details how this might affect copying the object, and the danger of dangling references and wild gone pointers if function() wants to save it for further usage.
MyType* savedPointer;
SomeType function(MyType* pointer) { savedPointer = pointer; };
a. valid for 1. and 2.
{
MyType t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
b. valid for 1. and 2.
{
const MyType& t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
c. valid for 1. and 2.
{
MyType& t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
d. valid for 3.
{
MyType* t = myClass.getMyType();
function(t);
}
// is savedPointer still valid here?
where myClass is an object of type MyClass.
You can provide both const and non-const versions:
MyType & MyClass::getMyType() { return mMyType; }
MyType const & MyClass::getMyType() const { return mMyType; }
I wouldn't provide a pointer version, since that implies that the return value might be the null pointer, which it can never be in this instance.
The real point, however, is that you are basically giving the caller direct access to the internal object. If this is your intent, then you may as well make the data member public. If it isn't, then you will need to work harder to hide the object.
One option is to retain the MyType const & accessor, but provide more indirect means to modify the internal object (setMyType(…) or something more tailored to the semantics that you are trying to express at the level of the containing class).
In general, you should prefer return by value, unless you
explicitly want to guarantee that the reference will designate
a member (which exposes part of your implementation, but is
desirable in cases like std::vector<>::operator[]). Returning
a reference prevents later changes in class, since it means that
you cannot return a calculated value. (This is especially
important if the class is designed to be a base class, since
returning a reference creates this restriction for all derived
classes.)
The only time you should return by pointer is if a lookup or
something is involved, which may return in having to return
a null pointer.
Returning a reference to const may be a valid optimization, if
the profiler indicates performance problems here, and the call
site can also deal with a const reference (no modification of
the returned value, no problems with lifetime of object). It
must be weighed against the additional constraints on the
implementation, of course, but in some cases, it is justified.
I would always return a const reference. If you need to modify the value it is returning just use a setter function.
Return by value, such as: MyType MyClass::getMyType() { return mMyType; } should be avoided as you will copy the content of your object. I do not see the gain you could have but I see the drawbacks on performance.
Return by const reference: const MyType& MyClass::getMyType() { return mMyType; } is more generaly used this way:
const MyType& MyClass::getMyType() const { return mMyType; }
MyType& MyClass::getMyType() { return mMyType; }
Always provide the const version. The non-const version is optional as it means that someone can modify your data. It is what I would encourage you to use.
Return by address: MyType* MyClass::getMyType() { return &mMyType; } is mostly used when the data is optionally there. It often has to be checked before being used.
Now, your use case, I would strongly advice not to keep a pointer save for more than a scope. I can often lead to ownership problems. I you have to do so, take a look to shared_ptr.
For your examples, there is two cases:
a. savedPointer won't be valid any more after the closing brace.
b,c, and d. savedPointer is valid after the closing brace, but beware it should not outlive myClass.
a) MyType t = will create a copy of the object for both 1 and 2. Saved pointer will not be valid once t is out of scope.
b) The saved pointer will be valid for the case returning a reference, but invalid for the case returning an object. For the reference, the lifetime of the pointer would be the same as myClass. Of course &t on a const ref would be a const t* not a t* and so would fail to cast in your call to function(MyType*).
c) Same as b, though the code is invalid for 2 because you can't cast a const MyType& to a MyType&. Generally this would be bad practice and the const form would be more acceptable.
d) savedPointer will have the same lifetime as myClass.
I'd generally lean toward either returning a reference or a const reference depending on what you expect to be able to do with the return value. If you return a reference (non-const), you can do things like: myClass.getMyType() = ..., while if you return a const reference, the object is read-only.

Return Value Optimization and const getters for data members [duplicate]

What is the best practice for a C++ getter method which is supposed to return a non trivial type, but a member which is of type class, or struct.
Return by value, such as: MyType MyClass::getMyType() { return mMyType; }
Return by const reference: const MyType& MyClass::getMyType() { return mMyType; }
Return by address: MyType* MyClass::getMyType() { return &mMyType; }
where
class MyType { /* ... */ };
class MyClass
{
private:
MyType mMyType;
}
I specifically worry about the following usages of this method. Can you please elaborate in details how this might affect copying the object, and the danger of dangling references and wild gone pointers if function() wants to save it for further usage.
MyType* savedPointer;
SomeType function(MyType* pointer) { savedPointer = pointer; };
a. valid for 1. and 2.
{
MyType t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
b. valid for 1. and 2.
{
const MyType& t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
c. valid for 1. and 2.
{
MyType& t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
d. valid for 3.
{
MyType* t = myClass.getMyType();
function(t);
}
// is savedPointer still valid here?
where myClass is an object of type MyClass.
You can provide both const and non-const versions:
MyType & MyClass::getMyType() { return mMyType; }
MyType const & MyClass::getMyType() const { return mMyType; }
I wouldn't provide a pointer version, since that implies that the return value might be the null pointer, which it can never be in this instance.
The real point, however, is that you are basically giving the caller direct access to the internal object. If this is your intent, then you may as well make the data member public. If it isn't, then you will need to work harder to hide the object.
One option is to retain the MyType const & accessor, but provide more indirect means to modify the internal object (setMyType(…) or something more tailored to the semantics that you are trying to express at the level of the containing class).
In general, you should prefer return by value, unless you
explicitly want to guarantee that the reference will designate
a member (which exposes part of your implementation, but is
desirable in cases like std::vector<>::operator[]). Returning
a reference prevents later changes in class, since it means that
you cannot return a calculated value. (This is especially
important if the class is designed to be a base class, since
returning a reference creates this restriction for all derived
classes.)
The only time you should return by pointer is if a lookup or
something is involved, which may return in having to return
a null pointer.
Returning a reference to const may be a valid optimization, if
the profiler indicates performance problems here, and the call
site can also deal with a const reference (no modification of
the returned value, no problems with lifetime of object). It
must be weighed against the additional constraints on the
implementation, of course, but in some cases, it is justified.
I would always return a const reference. If you need to modify the value it is returning just use a setter function.
Return by value, such as: MyType MyClass::getMyType() { return mMyType; } should be avoided as you will copy the content of your object. I do not see the gain you could have but I see the drawbacks on performance.
Return by const reference: const MyType& MyClass::getMyType() { return mMyType; } is more generaly used this way:
const MyType& MyClass::getMyType() const { return mMyType; }
MyType& MyClass::getMyType() { return mMyType; }
Always provide the const version. The non-const version is optional as it means that someone can modify your data. It is what I would encourage you to use.
Return by address: MyType* MyClass::getMyType() { return &mMyType; } is mostly used when the data is optionally there. It often has to be checked before being used.
Now, your use case, I would strongly advice not to keep a pointer save for more than a scope. I can often lead to ownership problems. I you have to do so, take a look to shared_ptr.
For your examples, there is two cases:
a. savedPointer won't be valid any more after the closing brace.
b,c, and d. savedPointer is valid after the closing brace, but beware it should not outlive myClass.
a) MyType t = will create a copy of the object for both 1 and 2. Saved pointer will not be valid once t is out of scope.
b) The saved pointer will be valid for the case returning a reference, but invalid for the case returning an object. For the reference, the lifetime of the pointer would be the same as myClass. Of course &t on a const ref would be a const t* not a t* and so would fail to cast in your call to function(MyType*).
c) Same as b, though the code is invalid for 2 because you can't cast a const MyType& to a MyType&. Generally this would be bad practice and the const form would be more acceptable.
d) savedPointer will have the same lifetime as myClass.
I'd generally lean toward either returning a reference or a const reference depending on what you expect to be able to do with the return value. If you return a reference (non-const), you can do things like: myClass.getMyType() = ..., while if you return a const reference, the object is read-only.

How to write a getter method so that it returns an rvalue

If we have this class definition
class BusDetails
{
private:
string m_busName;
public:
string BusName() const { return m_busName; }
};
how could the getter method be changed or used, so that using the return value as an lvalue would give a compiler error?
For example, if I use it like
int main(void)
{
BusDetails bus;
bus.BusName() = "abc"; // <--- This should give a compiler error
cout << bus.BusName() << endl;
return 0;
}
I get no compiler error, so apparently the assignment works, but the result is not as expected.
Update: this behavior is as expected with build-in types (i.e. the compiler gives an error at the above line of code if I have an int as a return type instead of string).
The BusName() was declared as a const function. So it can't change members.
Your function should return string& and not be const.
string& BusName() { return m_busName; }
In addition you can add for const object (this is const):
const string& BusName() const { return m_busName; }
It's not clear what behavior you want.
If you want the assignment to be an error, and keep all of the
flexibility of value return (e.g. you can modify the code to
return a calculated value), you can return std::string const.
(This will inhibit move semantics, but that's generally not
a big issue.)
If you want to be able to modify the "member", but still want
to retain flexibility with regards to how it is implemented in
the class, then you should provide a setter method. One
convention (not the only one) is to provide a getter function
like you have now (but returning std::string const), and
provide a function with the same name void
BusName( std::string const& newValue ) to set the value.
(Other conventions would use a name like SetBusName, or return
the old value, so client code could save and restore it, or
return *this, so client code could chain the operations:
obj.BusName( "toto" ).SomethingElse( /*...*/ ).
You may also provide a non-const member returning a reference
to a non-const. If you do this, however, you might as well make
the data member public.
Finally, you might provide a non-const member which returns
some sort of proxy class, so that assigning to it would in fact
call a setter function, and converting it to std::string would
call the getter. This is by far the most flexible, if you
want to support modifications by the client, but it's also by
far the most complex, so you might not want to use it unless you
need to.
Well it is kind of expected behavior what you have written.
You do return a copy of m_busName. Because you do not return the reference. Therefore a temporary copy of the return variable is made, and then the assignment takes place. operator= is "abc" called on that copy.
So the way to go would be string& BusName() const { return m_busName; }. But that shall give a compiler error.
You kind of want contradictory things. You say string BusName() const, yet you want to return a reference that will allow the state of the object to be changed.
However if you don't promise the object will not change you can drop the const and go with
string& BusName() { return m_busName; };
Or if you want to keep the const
const string& BusName() const { return m_busName; };
however this should give an error on the assignment, naturally.
The same goes for functions. If you do pass argument by reference it is a reference. If you see that you modify a copy, you must have not passed it by reference but by value.
The function does return an rvalue.
The problem is that std::string::operator= works with an rvalue on the left. Prior to C++11 it was difficult or impossible to prevent it from working: in C++11 they added (relatively late) what is colloquially known as rvalue references to this: the ability to overload methods and in-class operators based on the rvalue state of the object.
However, std::string was not modified, probably do to a mixture of not much time and dislike of breaking existing code without good reason.
You could patch around this problem a few ways. You could write your own string class that obeys rvalue reference to this. You could descend from std::string and block the operator= specifically. You could write an accessor object that has-a std::string that can cast-to std::string&& a d std::string& (based on rvalue status of this) implicitly, but blocks assignment with deleted method.
All three have issues. The last has the fewest issues, the second the most hidden pitfalls, the first is just drudgery.

Correct usage(s) of const_cast<>

As a common rule, it is very often considered a bad practice to use const_cast<>() in C++ code as it reveals (most of the time) a flaw in the design.
While I totally agree with this, I however wonder what are the cases were using const_cast<>() is ok and the only solution.
Could you guys please give me some examples you know/you encountered ?
Thank you very much.
it is pretty much designed to be only used with legacy APIs that are not const correct i.e. with a function you can't change that has non const interface but doesn't actually mutate anything on the interface
Like others have said, its primary purpose is to remove const from objects in order to pass to non-const correct functions you know won't modify the argument.
There is a trick (by Meyers?) to avoid code duplication, and it goes like this:
struct foo
{
const return_type& get(void) const
{
// fancy pants code that you definitely
// don't want to repeat
return theValue; // and got it
}
return_type& get(void)
{
// well-defined: Add const to *this,
// call the const version, then
// const-cast to remove const (because
// *this is non-const, this is ok)
return const_cast<return_type&>(static_cast<const foo&>(*this).get());
}
};
const_cast is also used to remove volatile modifiers, as put into practice in this (controversed) article:
http://www.drdobbs.com/184403766
I agree with your statement that its normal use is because you need to hide a 'design flaw'.
IME one of the typical usage scenarios is when you try to interface C++ to existing C code. A lot of existing C code takes C strings as char * even when the string is not modified whereas they're usually represented as something that converts to a const char * in C++. That's an impedance mismatch between the two languages that you would normally solve by using a const_cast. Of course you'd better be very sure that the code you're interfacing with doesn't get any cute ideas about modifying the data that's being passed in.
I would say that it's a code smells in newly written code, but for interfacing with older C and C++ code, it's an necessary evil. That said, I would be extremely wary of code that requires const_cast for any non-POD objects as that is normally a problem that should be solved at the design level and not the code level.
One legitimate use (in my opinion) is with std::set iterators. They are always const, in order to prevent changing the key used in the set. Changing the key would break the internal structure of the set and cause undefined behavior.
However, as long as the key doesn't change it's safe to change other data in the object.
Let's say you have an std::set like this:
std::set<MyObject> some_set;
And a class like this:
class MyObject {
public:
MyObject(const std::string &key)
: key_(key) {}
bool operator<(const MyObject &other) const {
return key_ < other.key_;
}
private:
// ...
// <some other data>
// ...
const std::string key_;
};
In the above example, the key is already const, so even if you modify the object, you cannot break the internal structure of the set.
Normally you can only get a const reference out of a set iterator:
const MyObject &object = *some_set_iterator;
But since the key is const, it's safe to const_cast the dereferenced iterator:
MyObject &object = const_cast<MyObject &>(*some_set_iterator);
One very legitimate use of this is when you have both a const and non const api (for const and non const objects respectively) as in
class Bar {
const SomeType& foo() const;
SomeType& foo();
}
Then since we don't want to duplicate the code in both functions we often use
class Bar {
SomeType& foo() {
//Actual implementation
}
const SomeType& foo() const {
return const_cast<Bar*>(this)->foo();
}
};
This is of course assuming that foo does not do something that violates the const semantics.
Yes of course, when your calling code that you can't modify and isn't const correct. It should be noted that you should only use it with calls to functions that you know for certain won't modify your data!
There is an example of const_cast usage in c++ primer(5th edition) book.
Below function returns reference to const string
// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
The book then mentions the case when we want a non const reference.
We can call the function on a pair of nonconst string arguments, but
we’ll get a reference to a const string as the result. We might want
to have a version of shorterString that, when given nonconst
arguments, would yield a plain reference. We can write this version of
our function using a const_cast:
string &shorterString(string &s1, string &s2)
{
auto &r = shorterString(const_cast<const string&>(s1),
const_cast<const string&>(s2));
return const_cast<string&>(r);
}
This version calls the const version of shorterString by casting its
arguments to references to const. That function returns a reference to
a const string, which we know is bound to one of our original,
nonconst arguments. Therefore, we know it is safe to cast that string
back to a plain string& in the return.
According to the book, it should be used if we know it is safe to cast.

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.