Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way (move semantics) to return a std::vector from function calling in C++11

I want to fill std::vector (or some other STL container):

class Foo { public:   Foo(int _n, const Bar &_m); private:   std::vector<Foo> fooes_; } 

1.Good looking ctor, expensive performance

std::vector<Foo> get_vector(int _n, const Bar &_m) {   std::vector<Foo> ret;   ... // filling ret depending from arguments   return ret; }  Foo::Foo(int _n, const Bar &_m) : fooes_(get_vector(_n, _m) {} 

2. Better performance, worse looking ctor

void fill_vector(int _n, const Bar &_m, std::vector<Foo> &_ret) {   ... // filling ret depending from arguments }  Foo::Foo(int _n, const Bar &_m) { fill_vector(_n, _m, fooes_); } 

Is it possible to rewrite get_vector function from 1st example with C++0x (move semantics features and so on) to avoid redundant copying and constructor calls?

like image 279
Loom Avatar asked Jun 02 '11 07:06

Loom


People also ask

Can you return a vector from a function C++?

Yes, a function can return a vector in C++ and in different ways. This article explains the different ways in which a C++ function can return a vector. In order to code a vector in C++, the vector library has to be included in the program.

How do you return a vector STD?

In C++11, this is the preferred way: std::vector<X> f(); That is, return by value. With C++11, std::vector has move-semantics, which means the local vector declared in your function will be moved on return and in some cases even the move can be elided by the compiler.

What is C++ move semantics?

Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.

What happens when you to std :: move?

std::move itself does "nothing" - it has zero side effects. It just signals to the compiler that the programmer doesn't care what happens to that object any more. i.e. it gives permission to other parts of the software to move from the object, but it doesn't require that it be moved.


2 Answers

If you're using a C++0x-compatible compiler and standard library, you get better performance from the first example without doing anything. The return value of get_vector(_n, _m) is a temporary, and the move constructor for std::vector (a constructor taking an rvalue reference) will automatically be called with no further work on your part.

In general, non-library writers won't need to use rvalue references directly; you'll just reap a decent chunk of the benefits automatically.

like image 134
John Calsbeek Avatar answered Oct 12 '22 22:10

John Calsbeek


I believe (1) and (2) have identical performance even without C++0x, as long as your compiler does the Named Return Value Optimization, which I believe most do. Neither should do any copies, nor any moves.

Please correct me if I'm wrong, because if so I misunderstand NRVO.

like image 32
Clinton Avatar answered Oct 13 '22 00:10

Clinton