C++ return by reference multiple times - c++

I have been using return by reference to try to speed up my code and avoid multiple expensive copy operations.
I have an access member function that looks like this:
std::string const& access_element(int index) const;
If I have another member function that calls access_element(), do I need to also return that by reference?
For instance.
float const& access_element2(int index) const {
return atof(access_element(index));
}
versus
float access_element2(int index) {
return atof(access_element(index));
}

You are returning by reference a temporary value.
In this case your bottleneck is in atof, not in returning a copy.
atof return a temporary value. If your intention is to speed up with a return by reference, you should return a member object, or a member object of a member object (like a vector item) that is returned by reference.
float const& access_element2(int index) const {
return elements[index];
}

Here's a good article: Want Speed? Pass by Value.
Also you really need to be careful with returning by reference. References are like pointers in that you can get dangling references which aren't legally usable. The following has undefined behavior:
int const &foo() {
return 1;
}
Also, when passing primitive types like float it's usually better to just copy them, because passing a pointer means you'll be copying a pointer instead, which is unlikely to be faster than copying the value itself. This answer has a good rule of thumb for taking parameters by reference vs. value: https://stackoverflow.com/a/1567186/365496
Another reason to pass by const & instead of by value is if making a copy could require heap memory allocations. Such copies could fail and so it's better to pass by reference to avoid that error possibility.

Related

Return a reference vs. passing a reference as parameter

What are the advantages and disadvantages of returning a reference in comparison to passing a reference as parameter.
I have a class which has a member variable ("localVariable" in the little code example) and via get-functions other classes should get the values of these member variables.
At the moment I have the following function:
in
int localVariable;
int getValue(){
return localVariable;
}
I was said that it's important so use const references
Which of the following functions would be appropriate?
Which are the advantages and disadvantages of every version?
int localVariable;
int const & getValue(){
return localVariable;
}
or
int localVariable;
void const getValue(&refValue){
refValue = localVariable;
}
I found something a bit similar but it's not exactly the same and so it is still not clear to me what is better in my case: Returning a pointer vs. passing a reference to an object to store the answer in C++
Return a const/reference or an object by value has the advantage that it can be used in an expression, while using a reference needs a variable where to copy the object.
Usually, pass/return by value is used for small objects and const/reference if they are larger. Note that pass/return by reference also has a cost. Weel, this has changed in c++11 because of the move copy/assignment.
On the other hand --you have used the name "localVariable"-- if you return a reference, you have to take into account that the returned variable must still exist after call return.
(The second one isn't a function, its a method).
Reference or not, its a case of readability, the question as asked is more function vs method. A function should return its primary objective, not set an output parameter. Typically a function typically operates on the parameters passed in and is algorithmic in nature.
(actually the example above looks like an encapsulated property)

C++ references and return values

I came across the following code:
class MyClass {
// various stuff including ...
double *myarray;
double &operator() (const int n){
return myarray[n];
}
double operator() (const int n) const {
return myarray[n];
}
// various other stuff ...
}
So what is the practical difference in those two overloads of "()"? I mean, I know "The first one returns a reference to a double and the second one returns a double," but what does this mean practically? When would I use the one and when would I use the other? The second one (returning a double) seems pretty safe and straightforward. Is the first one ever dangerous in some way?
They differ in that first one allows you to modify your array element, while the second one only returns value, so you can:
with: double &operator()
MyClass mm;
mm(1) = 12;
but also:
std::cout << mm(1);
with: double operator()
// mm(1) = 12; // this does not compile
std::cout << mm(1); // this is ok
also, returning a reference is more common when using operator[], like when you use std::vector::operator[].
btw. its common to have two versions of operator() - one const and second non-const. Const version will be called on const objects, while the second one on non const. But usually their signature is :
double& operator() (const int n);
const double& operator() (const int n) const;
In general, the difference between pointers and references is that pointers can be changed and can also point to nullptr, i.e. to nothing. References are fixed.
In this example, though, operator() does not return a reference but a copy of the value, i.e. changing the value retrieved that way does not change the double in the class.
If it truly returned a double&, then you could use both of these methods interchangeably (of course with different notations in the usage), and offering both would merely be a welcome convenience for the user of this class.
what does this mean practically?
It means that the second method returns by-value, i.e. it makes a copy of the array-item/double and returns that copy to the caller. The first method returns by-reference, i.e. it doesn't make a copy of the double, but rather returns a reference to the original/in-the-array double's location, which the calling code can then use to directly access the in-the-array double, if it wants to. (if it helps, the indirection semantics of the returned reference are somewhat like pointer semantics, except with a syntax that is more similar to the traditional C/C++ by-value functionality)
When would I use the one and when would I use the other?
The by-value method is safer, since there is less chance of invoking undefined behavior; the by-reference method gives you some more flexibility (i.e. the caller could then update the item in the array by writing to the reference he received as a return value) and it might be more efficient in some situations (e.g. returning a reference avoids the need to copy the object, which could be an expensive operation if the object is large or complex). For a small object like a double, returning by-value is likely more efficient than returning by-reference.
Is the [by-reference method] ever dangerous in some way?
It can be -- for example, if you were to return a reference to an automatic/stack variable, that would cause undefined behavior, since the variable would be destroyed before the calling code could use it:
double & dont_ever_do_this()
{
double x = 5.0; // x will be destroyed as this method returns!
return x; // so returning a reference to x is a silly thing to do
}
Similarly, in your MyClass example, if the caller holds on to the returned reference and then tries to use it after myarray has been deleted, the caller will be reading from (or writing to) a memory location that is no longer valid, and that will cause undefined behavior (read: Bad Things) to happen.
And of course returning a non-const reference means the caller has the ability to change the contents of the returned array item without your class being aware of it, which might not be something you want to allow.
You can see value categories from this link.
http://en.cppreference.com/w/cpp/language/value_category
In double& operator() case you have lvalue expression and can use like lvalue (for assignment, print etc.)
MyClass class;
class(7) = 21;
or
std::cout << class(7);
And in double operator() const case you have rvalue expression.
In this case you also can use it with const object.

Returning a reference from a function in c++

I would like to ask about returning a pointer from function.
Assuming that we have got
T *p;
This function should return a refrence to a T object. But it returns *p so it returns an value that it is pointing to. So is there no difference if we will write T& operator... or T operator...?
T& operator*() const{
if(p)
return *p;
throw std::runtime_error("unbound");
};
What is a difference between returning a reference and a value normally?
If you return a value (T operator...), you will return a new object, a copy of *p. If caller modifies the returned object, it won't affect your attribute variable. Returning by copy has a cost (CPU operations to create the copy + memory usage of the copied object). It also requires T to be capiable (to provide a valid copy constructor).
If you return by reference (T& operator...), you will return the address of the object (in the end, it's very similar to returning a poinetr T*, it costs the same, only syntax to use references is different than syntax to use pointers). If caller modifies the returned referenced object, it will affect your attribute variable (however, making the reference returned const T& will prevent that).
Reference is preferable (faster and better in term of memory usage), as far as you can guarantee that the referenced variable remains alive while caller will use the reference. For instance, if you are returning a local object created by the function, it must be returned by copy, not by reference).
Read more here: What are the differences between a pointer variable and a reference variable in C++?

When should I return by T const&?

When should I return by T const&? If I am not going to modify the object, I do not see how it is any different from returning by value. And returning by const reference really just means no copy is made. So when is returning by T const& useful.
There are two reasons why you would prefer to return by const& rather than by value.
The first is semantics. A code which returns something by const& is telling the caller explicitly, "here is a read-only version of what you asked for. If you want to store it permanently, or make changes to it, you are responsible for making a copy of it." The semantics of this return type are quite clear, and easily enforced.
The second is optimization. By returning something by-value, you remove some optimization opportunities from the compiler. That is not to say that returning by-value is less efficient than returning by const& (in fact, in cases the opposite might be true -- consider a function that returns a char on a 64-bit system). It simply means you remove one of the tools from the compiler's optimization toolbox. There is another tool there to replace it -- namely, inlining the call along with copy elision -- so this might be a wash. It all depends on context.
I mention "semantics" as the first reason because I consider it to be the most important. There are so many variables with optimization and so many moving parts that it's often hard to know just what optimizations the compiler will be able to employ and when. One thing is certian all the time however -- clear semantics are more easily understood by humans than muddled semantics.
A common case where you'd return const T& is a const getter member function:
T& get() { return m_some_private_member; }
const T& get() const { return m_some_private_member; }
In this case you often don't want to make a copy - you just want to return a reference to some object, and for the sake of const-correctness you may also need to provide a const getter.
When you have a sufficiently stable object.
One trivial case is for a collection that returns the content that way. Kinda the primary job description.
For nonconst & another usual case is to return what you got in arguments (including the hidden this pointer). That could apply to const& in a similar way, but be aware of risks, when your param was bound to a temporary that will disappear in short time. Would work better if you got & and return const& after changing the content.
You can return reference to a data member, but it fits the "do not leak your guts" guideline.
In any case if you return ref, you must provide documentation to the client on the validity. If you start working out that description, you will discover whether it makes sense in the first place.
Another obvious case is identity objects, that can (or supposed) not to be copied. It make sense to have to accessors, one returning const& for mainstream use and another with write access.
For the very reason you specified: no copy is made.
If you're returning a large object, it is much more efficient to return a const reference than a copy of the object.
Not making a copy is more efficient, especially for complex types, or types that do a lot of work in their copy constructor.
So you can avoid you function being misused as the one below does?
class A
{
int x;
public:
int show()
{
return x;
}
A(int a)
{
x = a;
}
A const& operator+(A& inp)
{
inp.x = this->x + inp.x;
return inp;
}
};
int main()
{
A a(1),b(2),c(0),d(420);
a + b = d;
std::cout<<b.show();
}
This gives, 420 as output. The overload is supposed to be used as d = a + b, but there is nothing stopping the returned reference to be assigned a another object.
If you make the return type of the function as A const& The returned reference is constant and cant be assigned any other object. Hence the operator has to be used only as d = a + b and not allowing a + b = d etc.
g++ gives error error: passing ‘const A’ as ‘this’ argument of ‘A& A::operator=(const A&)’ discards qualifiers and effectively prevents such misuse.

C++ beginner: what is the point of using a variable by reference if using "const"?

I was wondering about the logic in this function declaration:
CMyException (const std::string & Libelle = std::string(),...
What is the point of using a variable by reference? Usually you pass a variable by reference whenever it may be modified inside... so if you use the keyword const this means it'll never be modified.
This is contradictory.
May someone explain this to me?
Actually reference is used to avoid unnecessary copy of the object.
Now, to understand why const is used, try this:
std::string & x= std::string(); //error
It will give compilation error. It is because the expression std::string() creates a temporary object which cannot be bound to non-const reference. However, a temporary can be bound to const reference, that is why const is needed:
const std::string & x = std::string(); //ok
Now coming back to the constructor in your code:
CMyException (const std::string & Libelle = std::string());
It sets a default value for the parameter. The default value is created out of a temporary object. Hence you need const (if you use reference).
There is also an advantage in using const reference : if you've such a constructor, then you can raise exception like this:
throw CMyException("error");
It creates a temporary object of type std::string out of the string literal "error", and that temporary is bound to the const reference.
Some arguments might use quite some memory. If you pass an argument as value it will be copied and the copy will be passed to the method.
Passing them as reference will only pass the pointer to the method which is faster and saves the memory for the copy.
For example you can only do this with const reference argumernt:
CMyException("foo");
Think about it and then it will become clear.
Passing primitive types (int, char,..) by const reference doesn't make sense. Even for std::string I would argue it's not needed.
However, larger structures or classes require a copy when passing by value, so there's overhead there. A const reference simulates the behavior of passing by value (the outside variable isn't modified), but also prevents the extra copy.
No. It is not always necessary that whenever you pass any variable as reference it is only so that it may be modified inside. If the variable is passed by value then a copy of the variable is made whenever that function is called.
A reference variable on the other hand, uses the same object and essentially passes only the memory address (same as using std::string*, but with the exception that you cannot use a null memory address). So, when you do something like const std::string& x, what you're saying is:
1. The passed argument will not be copied. The same object will be used as in memory.
2. The function will absolutely not modify the object that it is handling.
If you think about it, using const makes sense when you're working with references and not otherwise. If you are making a copy of a variable that I pass and then modifying it, I couldn't really care less. However, it would be really nice to know for a fact that if you're not going to modify the very object I pass (as you will be using the very same object), I can strictly further define the process of my application under this guarantee.
I generally pass everything as const - I never modify the parameters, by value for primitive types, by reference for custom types. Passing by value for primitive types is more efficient in most of the cases - consider an unsigned short - by value 2 bytes, by reference 4-8 bytes depending on the pointer size.