Reputation: 12567
This questions is about C++98/C++03 rather than C++11, and is specific to the latest GCC (4.8) with the optimization turned on (e.g. -O3
)
If I'm working with large objects, e.g.
struct point {
float x, y;
};
typedef vector<point> points;
struct two {
points a, b;
};
when can I expect GCC to optimize the return
s of such objects from a function or method, such as
vector<two> large;
//...
return large;
Upvotes: 1
Views: 133
Reputation: 1
As Pepper_chico commented, it is related to return value optimization (RVO).
However, you could also consider the ABI specification for your particular implementation. The x86-64 ABI (and x86 calling conventions) specifies that on some occasions, a pair of registers can be used to return a small structure (instead of passing it on the stack)
BTW you could look at the generated assembly (using g++ -fverbose-asm -S -O3
) or at intermediate gimple representations (dumping a lot of files with them using g++ -fdump-tree-all -O3
, or using MELT ....).
Some "large" objects are actually implemented as pointers (fitting in a register). For instance instances of std::string
(on Linux, with libstdc++ from GCC 4.7 or 4.8, sizeof(std::string) == sizeof(void*)
), even if the underlying string has millions of bytes. Likewise, sizeof(std::vector<point>)
is often 3*sizeof(void*)
even for vectors of millions of point
-s ...
Upvotes: 1
Reputation: 14860
The well known rule of thumb for returning objects in C++98/03 is that you'll get most out of GCC if your objects can fit into your CPU register(s). Return such objects by value, return objects larger than this by a reference or a pointer.
With the C++11 standard there is more freedom for the compiler to move objects and of course for you to move them explicitly. With C++11 I'd start by returning everything you can by value and measure the hotpath coupled with inspecting the generated assembly to decide if switching to returning by references is worthwhile. A classic read on this is Want Speed? Pass by Value..
Upvotes: 1
Reputation: 145279
You can always expect efficiency when you have guaranteed it, e.g. by moving.
Otherwise it's a good to assume efficiency until the contrary has been proved by measuring.
g++ 4.8 implements most C++11 features including move semantics, and std::vector
does have move constructor (i.e., you're not dependent on RVO).
Upvotes: 1