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.
Related
When a function (callee) returns a quantity to the caller function, is it returned by
value or by reference?
The thing is I have written a function which builds a very large vector of when called. I want to return this big vector to the calling function , ( in this case main() ) by constant reference so I can do some further processing on it.
I was in doubt because I was told that when a C++ function returns and terminates, all the variables/memory associated with that function, get wiped clean.
struct node{
string key;
int pnum;
node* ptr;
}
vector< vector<node> > myfun1(/*Some arguments*/)
{
/*Build the vector of vectors. Call it V*/
return v;
}
int main(void)
{
a=myfun1(/* Some arguments */)
}
C++ functions can return by value, by reference (but don't return a local variable by reference), or by pointer (again, don't return a local by pointer).
When returning by value, the compiler can often do optimizations that make it equally as fast as returning by reference, without the problem of dangling references. These optimizations are commonly called "Return Value Optimization (RVO)" and/or "Named Return Value Optimization (NRVO)".
Another way to for the caller to provide an empty vector (by reference), and have the function fill it in. Then it doesn't need to return anything.
You definitely should read this blog posting: Want Speed? Pass by value.
By default, everything in C/C++ is passed by value, including return type, as in the example below:
T foo() ;
In C++, where the types are usually considered value-types (i.e. they behave like int or double types), the extra copy can be costly if the object's construction/destruction is not trivial.
With C++03
If you want to return by reference, or by pointer, you need to change the return type to either:
T & foo() ; // return a reference
T * foo() ; // return a pointer
but in both cases, you need to make sure the object returned still exists after the return. For example, if the object returned was allocated on stack in the body of the function, the object will be destroyed, and thus, its reference/pointer will be invalid.
If you can't guarantee the object still exists after the return, your only solution is to either:
accept the cost of an extra copy, and hope for a Return Value Optimization
pass instead a variable by reference as a parameter to the function, as in the following:
void foo(T & t) ;
This way, inside the function, you set the t value as necessary, and after the function returns, you have your result.
With C++11
Now, if you have the chance to work with C++0x/C++11, that is, with a compiler that supports r-values references/move semantics, if your object has the right constructor/operator (if your object comes from the standard library, then it's ok), then the extra temporary copy will be optimized away, and you can keep the notation:
T foo() ;
Knowing that the compiler will not generate an unnecessary temporary value.
C++ can return either by reference or by value. If you want to return a reference, you must specify that as part of the return type:
std::vector<int> my_func(); // returns value
std::vector<int>& my_func(); // returns reference
std::vector<int> const& my_func(); // returns constant reference
All local (stack) variables created inside of a function are destroyed when the function returns. That means you should absolutely not return locals by reference or const reference (or pointers to them). If you return the vector by value it may be copied before the local is destroyed, which could be costly. (Certain types of optimizations called "return value optimization" can sometimes remove the copy, but that's out of the scope of this question. It's not always easy to tell whether the optimization will happen on a particular piece of code.)
If you want to "create" a large vector inside of a function and then return it without copying, the easiest way is to pass the vector in to the function as a reference parameter:
void fill_vector(std::vector<int> &vec) {
// fill "vec" and don't return anything...
}
Also note that in the recently ratified new version of the C++ standard (known as C++0x or C++11) returning a local vector by value from a function will not actually copy the vector, it will be efficiently moved into its new location. The code that does this looks identical to code from previous versions of C++ which could be forced to copy the vector. Check with your compiler to see whether it supports "move semantics" (the portion of the C++11 standard that makes this possible).
It's returned by whatever you declare the return type to be. vector<int> f(); and vector<int>& f(); return by value and reference respectively. However, it would be a grave error to return a reference to a local variable in the function as it will have been blown away when the function scope exits.
For good tips on how to efficiently return large vectors from a function, see this question (in fact this one is arguably a duplicate of that).
The function will return what you tell it to return. If you want to return a vector, then it will be copied to the variable hold by the caller. Unless you capture that result by const reference, in which case there is no need to copy it. There are optimizations that allow functions to avoid this extra copy-constructon by placing the result in the object that will hold the return value. You should read this before changing your design for performance:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
Like most things in C++, the answer is "it depends on how you defined the function".
The default for the language is return-by-value. A simple call like "double f()" is going to always return the floating-point number by value. However, you CAN return values by pointer or by reference- you just add the extra symbols '&' or '*' to the return type:
// Return by pointer (*)
T* f();
// Return by reference (a single '&')
T& f();
However, these are ridiculously unsafe in many situations. If the value the function is returning was declared within the function, the returned reference or pointer will point to random garbage instead of valid data. Even if you can guarantee that the pointed-to data is still around, this kind of return is usually more trouble than it is worth given the optimizations all modern C++ compilers will do for you. The idiomatic, safe way to return something by reference is to pass a named reference in as a parameter:
// Return by 'parameter' (a logical reference return)
void f(T& output);
Now the output has a real name, and we KNOW it will survive the call because it has to exist before the call to 'f' is even made. This is a pattern you will see often in C++, especially for things like populating a STL std::vector. Its ugly, but until the advent of C++11 it was often faster than simply returning the vector by value. Now that return by value is both simpler and faster even for many complex types, you will probably not see many functions following the reference return parameter pattern outside of older libraries.
All variables defined on the stack are cleaned upon exit.
To return a variable you should allocate it on the heap, which you do with the new keyword (or malloc).
Classes and structs are passed around as pointers, while the primitive types are passed around as values.
Quite new to C++. I have seen people usually pass objects by reference in operator overloading. Well, I can't figure out when it is really necessary. As in the code below, if I remove ampersand in declaration of object c1 and c2 in operator+, still I'll get the same result. Is there any reason to pass-by-reference in this case when we do not want to modify c1 or c2?
#include <iostream>
class Keys
{
private:
int m_nKeys;
public:
Keys(int nKeys) { m_nKeys = nKeys; }
friend Keys operator+(const Keys &c1, const Keys &c2);
int GetKeys() { return m_nKeys; }
};
Keys operator+(const Keys &c1, const Keys &c2)
{
return Keys(c1.m_nKeys + c2.m_nKeys);
}
int main()
{
Keys cKeys1(6);
Keys cKeys2(8);
Keys cKeysSum = cKeys1 + cKeys2;
std::cout << "There are " << cKeysSum.GetKeys() << " Keys." << std::endl;
system("PAUSE");
return 0;
}
Operators are just like ordinary functions, just with "fancy" names :)
(e.g. operator+() instead of sum())
So, the same parameter passing rules that you apply to functions, can be applied to overloaded operators as well.
In particular, when you have a parameter that is not cheap to copy (e.g. an int, a float, are examples of cheap to copy parameters; a std::vector, a std::string, are examples of not cheap to copy parameters), and you observe this parameter inside your method (i.e. it's an input read-only parameter), then you can pass it by const reference (const &).
In this way, basically it's just like the address of the original argument is passed to the function, so there is no deep-copy involved. Deep-copies can be very expensive, e.g. think of a vector with a big number of elements.
So, to recap, you pass by const reference when:
the parameter just is not cheap to copy (e.g. for ints, float, etc. just
don't bother: passing by value is just fine)
the parameter is observed in the function/operator implementation
(i.e. it's an input read-only parameter)
If you pass by reference then there is no copy of the object made, which for more complicated classes could greatly improve performance.
In this case the performance cost may be marginal, and it's conceivable the compiler could optimise it all out, but it's still worth doing. Later the Keys class may change into something more complex.
Advantages of passing by reference:
It allows us to have the function change the value of the argument, which is sometimes useful.
Because a copy of the argument is not made, it is fast, even when used with large structs or classes.
We can pass by const reference to avoid unintentional changes.
We can return multiple values from a function.
Disadvantages of passing by reference:
Because a non-const reference can not be made to a literal or an expression, reference arguments must be normal variables.
It can be hard to tell whether a parameter passed by reference is meant to be input, output, or both.
It’s impossible to tell from the function call that the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.
Because references are typically implemented by C++ using pointers, and dereferencing a pointer is slower than accessing it directly, accessing values passed by reference is slower than accessing values passed by value.
You can read the below:
http://www.cs.fsu.edu/~myers/c++/notes/references.html
Consider a vector of long having 10 million entries in it. If you prototype a function like:
void foo(vector<long> vl)
{
}
It will cause assignment-operator (or copy-constructor) of vector<long> - and that would need to copy all those 10m elements. Later destructor for this temporary object (vl) would de-allocate memory and perform other cleanup. It will definitely impact performance
There are classes, specially around synchronization providers (critical sections etc.), and some smart pointer classes that prevent copy-constructor and/or assignment-operators - so that assignment or object creation doesn't happen by mistake. Though move-constructor or move-assignment-operator may be implemented.
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.
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.
When a function (callee) returns a quantity to the caller function, is it returned by
value or by reference?
The thing is I have written a function which builds a very large vector of when called. I want to return this big vector to the calling function , ( in this case main() ) by constant reference so I can do some further processing on it.
I was in doubt because I was told that when a C++ function returns and terminates, all the variables/memory associated with that function, get wiped clean.
struct node{
string key;
int pnum;
node* ptr;
}
vector< vector<node> > myfun1(/*Some arguments*/)
{
/*Build the vector of vectors. Call it V*/
return v;
}
int main(void)
{
a=myfun1(/* Some arguments */)
}
C++ functions can return by value, by reference (but don't return a local variable by reference), or by pointer (again, don't return a local by pointer).
When returning by value, the compiler can often do optimizations that make it equally as fast as returning by reference, without the problem of dangling references. These optimizations are commonly called "Return Value Optimization (RVO)" and/or "Named Return Value Optimization (NRVO)".
Another way to for the caller to provide an empty vector (by reference), and have the function fill it in. Then it doesn't need to return anything.
You definitely should read this blog posting: Want Speed? Pass by value.
By default, everything in C/C++ is passed by value, including return type, as in the example below:
T foo() ;
In C++, where the types are usually considered value-types (i.e. they behave like int or double types), the extra copy can be costly if the object's construction/destruction is not trivial.
With C++03
If you want to return by reference, or by pointer, you need to change the return type to either:
T & foo() ; // return a reference
T * foo() ; // return a pointer
but in both cases, you need to make sure the object returned still exists after the return. For example, if the object returned was allocated on stack in the body of the function, the object will be destroyed, and thus, its reference/pointer will be invalid.
If you can't guarantee the object still exists after the return, your only solution is to either:
accept the cost of an extra copy, and hope for a Return Value Optimization
pass instead a variable by reference as a parameter to the function, as in the following:
void foo(T & t) ;
This way, inside the function, you set the t value as necessary, and after the function returns, you have your result.
With C++11
Now, if you have the chance to work with C++0x/C++11, that is, with a compiler that supports r-values references/move semantics, if your object has the right constructor/operator (if your object comes from the standard library, then it's ok), then the extra temporary copy will be optimized away, and you can keep the notation:
T foo() ;
Knowing that the compiler will not generate an unnecessary temporary value.
C++ can return either by reference or by value. If you want to return a reference, you must specify that as part of the return type:
std::vector<int> my_func(); // returns value
std::vector<int>& my_func(); // returns reference
std::vector<int> const& my_func(); // returns constant reference
All local (stack) variables created inside of a function are destroyed when the function returns. That means you should absolutely not return locals by reference or const reference (or pointers to them). If you return the vector by value it may be copied before the local is destroyed, which could be costly. (Certain types of optimizations called "return value optimization" can sometimes remove the copy, but that's out of the scope of this question. It's not always easy to tell whether the optimization will happen on a particular piece of code.)
If you want to "create" a large vector inside of a function and then return it without copying, the easiest way is to pass the vector in to the function as a reference parameter:
void fill_vector(std::vector<int> &vec) {
// fill "vec" and don't return anything...
}
Also note that in the recently ratified new version of the C++ standard (known as C++0x or C++11) returning a local vector by value from a function will not actually copy the vector, it will be efficiently moved into its new location. The code that does this looks identical to code from previous versions of C++ which could be forced to copy the vector. Check with your compiler to see whether it supports "move semantics" (the portion of the C++11 standard that makes this possible).
It's returned by whatever you declare the return type to be. vector<int> f(); and vector<int>& f(); return by value and reference respectively. However, it would be a grave error to return a reference to a local variable in the function as it will have been blown away when the function scope exits.
For good tips on how to efficiently return large vectors from a function, see this question (in fact this one is arguably a duplicate of that).
The function will return what you tell it to return. If you want to return a vector, then it will be copied to the variable hold by the caller. Unless you capture that result by const reference, in which case there is no need to copy it. There are optimizations that allow functions to avoid this extra copy-constructon by placing the result in the object that will hold the return value. You should read this before changing your design for performance:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
Like most things in C++, the answer is "it depends on how you defined the function".
The default for the language is return-by-value. A simple call like "double f()" is going to always return the floating-point number by value. However, you CAN return values by pointer or by reference- you just add the extra symbols '&' or '*' to the return type:
// Return by pointer (*)
T* f();
// Return by reference (a single '&')
T& f();
However, these are ridiculously unsafe in many situations. If the value the function is returning was declared within the function, the returned reference or pointer will point to random garbage instead of valid data. Even if you can guarantee that the pointed-to data is still around, this kind of return is usually more trouble than it is worth given the optimizations all modern C++ compilers will do for you. The idiomatic, safe way to return something by reference is to pass a named reference in as a parameter:
// Return by 'parameter' (a logical reference return)
void f(T& output);
Now the output has a real name, and we KNOW it will survive the call because it has to exist before the call to 'f' is even made. This is a pattern you will see often in C++, especially for things like populating a STL std::vector. Its ugly, but until the advent of C++11 it was often faster than simply returning the vector by value. Now that return by value is both simpler and faster even for many complex types, you will probably not see many functions following the reference return parameter pattern outside of older libraries.
All variables defined on the stack are cleaned upon exit.
To return a variable you should allocate it on the heap, which you do with the new keyword (or malloc).
Classes and structs are passed around as pointers, while the primitive types are passed around as values.