Coming from a Java background, I am trying to understand pointers/references in C++. I am trying to return a vector from a function. Writing:
vector<char*> f(){
vector<char*> vec;
return vec;
}
would return the copy of the vector, correct? A better way would be to return a pointer to vector like this:
vector<char*>* f(){
vector<char*>* vec = new vector<char*>;
return vec;
}
Am I correct, or is this totally wrong?
In C++03 the returning by value most likely leads to RVO (Return Value Optimization) which will elide the unnecessary copy. In C++11 move semantics will take care of the copy.
So, why return by value in the first place? Because it prevents unnecessary objects with dynamic lifetimes. Your example code also doesn't respect any allocation policy a user of your function might want to use.
In general, returning a container is even in C++11 still a bad idea: It restricts users to that specific container as it is not possible to move across containers, only to copy. The standard library solves this problem with OutputIteratorS. Your algorithm would most likely be written as:
template<typename OutputIterator>
OutputIterator f(OutputIterator o);
This way you abstract away from the container and also circumvent the original problem.
You're wrong, you do not want to do this in C++. Pretty much every C++ compiler out there has what's called Named Return Value Optimization, which will (effectively) cause the vec to be moved, not copied, by allocating space for the return value on the stack, which is then basically constructed "in place". This eliminates the overhead.
The Wikipedia article on this gives a reasonable rundown.
Am I correct, or is this totally wrong?
This is totally wrong, at least in C++11 where move semantics exists, and as long as you do not need to create aliases of the value you return (which does not seem to be your case and, even if it were, would likely require the use of smart pointers rather than raw pointers).
Returning a vector by value is OK now. Most of the time, even in C++98, the compiler would elide the call to the copy constructor anyway (and to the move constructor in C++11). This is called the (Named) Return Value Optimization.
In C++11, all the containers of the Standard Library support move constructors, so even when a copy or move is not elided, returning a container by value is not expensive.
Related
struct big_struct{
vector<int> a_vector;
map<string, int> a_map;
};
big_struct make_data(){
big_struct return_this;
// do stuff, build that data, etc
return return_this;
}
int main(){
auto data = make_data();
}
I have seen move semantics applied to constructors, but in this bit of code, I'm wondering if the big struct is copied entirely when returned or not. I'm not even sure it is related to move semantics. Does C++ always copies this kind of data, or is it optimized? Could this code be change or improved?
What about a function that returns a vector or a map? Is that map/vector copied?
You don't need to change anything. What you have right now is the rule of zero. Since both std::map and std::vector are moveable your class automatically gets move operations added to it.
Since return_this is a function local object it will be treated as an rvalue and it will either be moved for you or NRVO will kick in and no move or copy will happen.
Your code will either produce a default construction call for return_this and a move constructor call for data or you will see a single default constructor call for data (NRVO makes return_this and data the same thing).
As stated here, your class actually has a move-constructor (implicitly generated one), so it shouldn't be copied in your code, at least once (in main).
One problem is, what you're relying upon is called NRVO, and compilers are not required to implement it (unlike its happier simpler brother, RVO.) So your struct has a chance, quite very small, to be copied in the return statement—but so small that return-by-move (like return std::move(return_this);) is never actually recommended. Chances are quite high the NRVO will actually be applied if you really have a single return statement in your function that returns a single named object.
I'm still not quite sure when return-by-value is a good idea in C++ an when not. In the following case, is it ok?
vector<int> to_vec(const Eigen::MatrixXi& in){
vector<int> out;
// copy contents of in into out
return out;
}
Eigen::MatrixXi to_eigen(const vector<int>& in){
Eigen::MatrixXi out;
// copy contents of in into out
return out
}
Depending on how those objects vector and MatrixXi actually work, it could result in an expensive copy. On the other hand, I assume that they leverage C++'s move functionality to inexpensively copy the by reusing the underlying data.
Without exactly knowing the implementation, what can I assume?
In such a situation where you're declaring a local variable, initializing it and returning it by value, you can be pretty safe in assuming that your compiler will elide the copy.
This case is known as named return value optimization. Essentially, instead of allocating the return value in the function call, it'll be done at the call site and passed in as a reference. Returning by value is the best choice here, as you don't need to declare a variable at the call site to pass in, but the performance will be as if you had.
In C++17, copy elision will be mandatory in most cases involving prvalues (e.g. T t = get_t(); or return get_t()), but is still optional for NRVO.
The Thumb rules regarding return values in C++ are:
never return a reference to a local variable
never return a pointer to a local variable
don't return a named value using move semantics
as for (3) - This is a known concern with C++ - we all learned that when an object returns by value - it activates the copy constructor. this is theoretically true, but practically wrong. the compiler will utilize copy elision on objects when optimization are turned on.
copy elision is an optimization technique that makes the value be created within the caller scope and not in the callee scope, hence preventing an expensive copy. modification on that object will take place in the callee scope.
as for (1) and (2), there is also a corner case regarding coroutines and generators, but unless you know you're dealing with them, (1) and (2) are always valid.
When I want a function to return me a container:
vector<T> func(){
vector<T> result;
...
return result;
}
To be used in the following way:
vector<T> result = func();
In order to avoid the overhead of copying my container
I often write the function so that it returns nothing but accept a
non-const instance of the container.
void func(vector<T>& result){
result.clear();
...
result;
}
To be used in the following way:
vector<T> result;
func(result);
Is my effort meaningless because I can be sure that the compiler
always uses the return value optimization?
It is meaningless. The type of RVO you mentioned is called named RVO (NRVO), and most compilers implement it.
Regardless, in C++11, vector has move constructors, so even if NRVO didn't apply, it'd still be moved, not copied.
RVO is not guaranteed but decent compilers will use it when permitted.
However the problem is RVO only helps when you are creating a new object outside the function. If you reuse the same vector by passing it by reference, you can take advantage of its reserved capacity to reduce the number of memory allocations. A local vector created inside the function will always need to allocate a new buffer internally, no matter where the return value is stored. Therefore it can be more efficient to pass the vector by reference, even though the code looks less nice.
Depends on age of your compiler. Before C++11, your alternative approach is what is needed unless the compiler supports named return value optimisation - which not all older compilers do. Also, you could also have the function return a reference to the passed vector.
From C++11, the language supports move construction, and the standard containers have working move constructors, so your first approach is fine. Purists will insist that is better. Pragmatists (who realise that not everyone can update their compilers without a huge impost) will say to pick a solution depending on whether your code needs to continue working with a mix of pre-C++11 and later compilers.
I've tried it with gcc. I realized that I cannot rely on NRVO when compiling without C++11 flags.
Since I don't like the second signature (where the function takes the container by reference) I came out with this:
Declare the function in its natural form:
vector<T> func(){
vector<T> result;
...
return result;
}
and, when I am not sure about the compiler and the compilation flags, use it in this way:
vector<T> result;
func().swap(result)
in this way one gets the wanted interface and is sure to avoid elidible overheads.
Notice that the capacity of the result vector is the one of the vector returned by the function. If one wants to set the capacity for the vector, the right interface for the function is the second one.
In my current project I need to implement quite a few functions/methods that take some parameters and generate a collection of results (rather large). So in order to return this collection without copying, I can either create a new collection and return a smart pointer:
boost::shared_ptr<std::vector<Stuff> > generate();
or take a reference to a vector which will be populated:
void generate(std::vector<Stuff> &output);
Both approaches have benefits. The first clearly shows that the vector is the output of the function, it is trivial to use in a parallelized scenario, etc. The second might be more efficient when called in a loop (because we don't allocate memory every time), but then it is not that obvious that the parameter is the output, and someone needs to clean the old data from the vector...
Which would be more customary in real life (i.e. what is the best practise)? In C#/java I would argue that the first one, what is the case in C++?
Also, is it possible to effectively return a vector by value using C++11? What would the pitfalls be?
do correctness first, then optimize if necessary
with both move semantics and Return Value Optimization conspiring to make an ordinary function result non-copying, you would probably have to work at it to make it sufficiently inefficient to be worth optimization work
so, just return the collection as a function result, then MEASURE if you feel that it's too slow
You should return by value.
is it possible to effectively return a vector by value using C++11?
Yes, C++11 supports move semantics. You return a value, but the compiler knows it's a temporary, and therefore can invoke a special constructor (move constructor) that is especially designed to simply "steal the guts" of the returned object. After all, you won't use that temporary object anymore, so why copying it when you can just move its content?
Apart from this, it may be worth mentioning that most C++ compilers, even pre-C++11, implement (Named) Return Value Optimization, which would elide the copy anyway, incurring in no overhead. Thus, you may want to actually measure the performance penalty you (possibly) get before optimizing.
I think you should pass by reference, or return a shared pointer, only when you need reference semantics. This does not seem to be your case.
There is an alternative approach. If you can make your functions template, make them take an output iterator (whose type is a template argument) as argument:
tempalte<class OutputIterator>
void your_algorithm(OutputIterator out) {
for(/*condition*/) {
++out = /* calculation */;
}
}
This has the advantage that the caller can decide in what kind of collection he wants to store the result (the output iterator could for instance write directly to a file, or store the result in a std::vector, or filter it, etc.).
The best practise will probably be surprising to you. I would recommend returning by value in both C++03 and C++11.
In C++03, if you create a std::vector local to generate and return it, the copy may be elided by the compiler (and almost certainly will be). See C++03 §12.8/15:
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function's return value
In C++11, if you create a std::vector local to generate and return it, the copy will first be considered as a move first (which will already be very fast) and then that may be elided (and almost certainly will be). See C++11 §12.8/31:
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
And §12.8/32:
When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
So return by value!
Believe it or not, I'm going to suggest that instead of either of those approaches just take the obvious implementation and return by value! Compilers are very often able to optimize away the notional copy that would be induced, removing it completely. By writing the code in the most obvious manner you make it very clear to future maintainers what the intent is.
But let's say you try return by value and your program runs too slow and let's further suppose that your profiler shows that the return by value is in fact your bottleneck. In this case I would allocate the container on the heap and return as an auto_ptr in C++03 or a unique_ptr in C++11 to clearly indicate that ownership is being transferred and that the generate isn't keeping a copy of that shared_ptr for its own purposes later.
Finally, the series at http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ provides a great perspective on almost the exact same question.
I need to get this straight. With the code below here:
vector<unsigned long long int> getAllNumbersInString(string line){
vector<unsigned long long int> v;
string word;
stringstream stream(line);
unsigned long long int num;
while(getline(stream, word, ',')){
num = atol(word.c_str());
v.push_back(num);
}
return v;
}
This sample code simply turns an input string into a series of unsigned long long int stored in vector.
In this case above, if I have another function calls this function, and we appear to have about 100,000 elements in the vector, does this mean, when we return it, a new vector will be created and will have elements created identically to the one in the function, and then the original vector in the function will be eliminated upon returning? Is my understanding correct so far?
Normally, I will write the code in such a way that all functions will return pointer when it comes to containers, however, program design-wise, and with my understanding above, should we always return a pointer when it comes to container?
The std::vector will most likely (if your compiler optimizations are turned on) be constructed directly in the function's return value. This is known as copy/move elision and is an optimization the compiler is allowed to make:
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
This quote is taken from the C++11 standard but is similar for C++03. It is important to note that copy/move elision does not have to occur at all - it is entirely up to the compiler. Most modern compilers will handle your example with no problems at all.
If elision does not occur, C++11 will still provide you with a further benefit over C++03:
In C++03, without copy elision, returning a std::vector like this would have involved, as you say, copying all of the elements over to the returned object and then destroyed the local std::vector.
In C++11, the std::vector will be moved out of the function. Moving allows the returned std::vector to steal the contents of the std::vector that is about to be destroyed. This is much more efficient that copying the contents over.
You may have expected that the object would just be copied because it is an lvalue, but there is a special rule that makes copies like this first be considered as moves:
When the criteria for elision of a copy operation are met [...] and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
As for whether you should return a pointer to your container: the answer is almost certainly no. You shouldn't be passing around pointers unless its completely necessary, and when it is necessary, you're much better off using smart pointers. As we've seen, in your case it's not necessary at all because there's little to no overhead in passing it by value.
It is safe, and I would say preferable, to return by value with any reasonable compiler. The C++ standard allows copy elision, in this case named return value optimization (NRVO), which means this extra copy you are worried about doesn't take place.
Note that this is a case of an optimization that is allowed to modify the observable behaviour of a program.
Note 2. As has been mentioned in other answers, C++11 introduces move semantics, which means that, in cases where RVO doesn't apply, you may still have a very cheap operation where the contents of the object being returned are transfered to the caller. In the case of std::vector, this is extremely cheap. But bear in mind that not all types can be moved.
Your understanding is correct.
But compilers can apply copy elision through RVO and NRVO and remove the extra copy being generated.
Should we always return a pointer when it comes to container?
If you can, ofcourse you should avoid retun by value especially for non POD types.
That depends on whether or not you need reference semantics.
In general, if you do not need reference semantics, I would say you should not use a pointer, because in C++11 container classes support move semantics, so returning a collection by value is fast. Also, the compiler can elide the call to the moved constructor (this is called Named Return Value Optimization or NRVO), so that no overhead at all will be introduced.
However, if you do need to create separate, consistent views of your collection (i.e. aliases), so that for instance insertions into the returned vector will be "seen" in several places that share the ownership of that vector, then you should consider returning a smart pointer.