How to check C ++ copy of ellision

I looked at this article on copy ellision in C ++, and I saw comments about this in the boost library. This is attractive because I prefer my features to look like

verylargereturntype DoSomething(...) 

but not

 void DoSomething(..., verylargereturntype& retval) 

So, I have two questions about this.

  • Google has practically no documentation on this subject, how realistic is it?
  • How can I check if this optimization is really? I suppose this involves looking at the assembly, but lets just say that this is not my strong suit. If someone can give a very simple example of what a successful ellipse looks like, that would be very helpful.

I will not use copying just to present things, but if I can be guaranteed that it works, it will be very useful.

+4
source share
7 answers

I think this is a very often used optimization, because:

  • This is not difficult for the compiler to do.
  • it can be a huge win
  • this is a C ++ area that was usually criticized before optimization became common.

If you're just curious, put the printf() debugger in your copy constructor:

 class foo { public: foo(): x(0) {}; foo(int x_) : x( x_) {}; foo( foo const& other) : x( other.x) { printf( "copied a foo\n"); }; static foo foobar() { foo tmp( 2); return tmp; } private: int x; }; int main() { foo myFoo; myFoo = foo::foobar(); return 0; } 

Prints "copied foo" when I run unoptimmized build, but havenโ€™t optimized anything.

+9
source

From the above article:

Although the copy standard is never required by the standard, the latest versions of every tested Ive compiler do perform these optimizations today. But even if you donโ€™t feel comfortable returning heavy objects by value, a copy of elision should still change the way you write code.

It is better known as Return Value Optimization .

+5
source

The only way to know for sure is to look at the assembly, but you are asking the wrong question. You do not need to know if the compiler copies the copy if it does not matter for program time. The profiler should easily tell you if you spend too much time on the copy constructor.

A bad way to figure this out is to put a static counter in the copy constructor and try both forms of your function. If the counts match, you successfully avoid the copy.

+3
source

Google "Named Return Value Optimization" and "Return Value Optimization." Modern compilers in many cases will not execute a copy.

You can check if this happens by returning a type with side effects - for example, printing a message. Wikipedia has some good examples of where the output of a program changes when RVO and / or NRVO are in effect.

+2
source

An example of what it looks like:

 #include <iostream> struct Foo { int a; Foo(int a) : a(a) {} Foo(const Foo &rhs) : a(rhs.a) { std::cout << "copying\n"; } }; int main() { Foo f = Foo(1); } 

If you do not see a way out, then copying will occur. This is a copy exception from the initializer. Another legitimate copy case is the return value and is checked:

 Foo getFoo() { return Foo(1); } int main() { Foo f = getFoo(); } 

or more fun for a named return value:

 Foo getFoo() { Foo f(1); return f; } int main() { Foo f = getFoo(); } 

g ++ fulfills all these exceptions for me without optimization flags, but you cannot know if the more complex code will exceed the compiler.

Note that the copy exception does not help with the assignment, so when calling operator= following will always be done: if this operator prints something:

 Foo f(1); f = getFoo(); 

Returning by value, it can still lead to "copying", even if the copy constructor query is executed. Thus, in order to classify classrooms, this is still being considered at the design stage. You do not want to write your code in such a way that fixing it later will be of great importance if it turns out that your application spends a significant part of the time on copying, which could be avoided.

+2
source

To answer question 2, you can write a demo program in which you write class DemoReturnType; , which has instrumental constructors and destructors that are simply written to cout when called. This should give you enough information about what your compiler is capable of.

+1
source

Rvalue links solve this problem in C ++ 0x. Regardless of whether you can get a compiler with rvalue support - this is another question - the last time I tested only Visual Studio 2010 support.

+1
source

Source: https://habr.com/ru/post/1306060/


All Articles