C + + return value optimization

Source: Internet
Author: User

return value optimization (Return values optimization, abbreviated RVO) is a compiler optimization mechanism: When a function needs to return an object, if it creates a temporary object for return, Then this temporary object consumes the call of a constructor (Constructor), the invocation of a copy constructor (copy Constructor), and the invocation of a destructor (destructor).

After the return value is optimized, the cost can be reduced to a single constructor. This eliminates the call of a copy constructor and the invocation of the destructor in turn.

Examples are as follows:

Class MyString {public:mystring () {_data = NULL;         _len = 0;    printf ("Constructor is called!\n");         } MyString (const char* p) {_len = strlen (p);         _init_data (P); cout << "Constructor is called!    This->_data: "<< (long) _data << Endl;         } MyString (const mystring& str) {_len = Str._len;         _init_data (Str._data); cout << "Copy Constructor is called!    SRC: "<< (long) str._data <<" DST: "<< (long) _data << Endl; } ~mystring () {if (_data) {cout << "Deconstructor is called!             This->_data: "<< (long) _data << Endl;        Free (_data);         } else {std::cout << "Deconstructor is called!" << Std::endl;              }} mystring& operator= (const mystring& str) {if (This! = &str) {_len = Str._len; _init_data (Str._daTA); } cout << "Copy assignment is called!         SRC: "<< (long) str._data <<" DST "<< (long) _data << Endl;     return *this;    } operator Const char * () const {return _data; } void Display () const {if (_data) {cout << "str is" << _data << "(" &        lt;< (long) _data << ")" << Endl;        } else {cout << "nothing" << Endl;     }}private:char *_data;     size_t _len;         void _init_data (const char *s) {_data = new char[_len+1];         memcpy (_data, S, _len);     _data[_len] = ' + '; } }; MyString foo1 () {return MyString ("123");}    MyString Foo2 () {MyString str1 ("456"); return str1;}    int main () {foo1 ();    cout << "--------------------\ n";    Foo2 ();    cout << "--------------------\ n";    MyString str1 = Foo1 ();    cout << "--------------------\ n"; MyString str2 =Foo2 ();    cout << "--------------------\ n"; return 0;}

The function foo1 directly returns a temporary object, and Foo2 returns a local variable. In the absence of Rvo, whether calling Foo1 or Foo2, the constructor is actually called first, and then the copy constructor is called to construct the temporary object as the return value. The copy constructor is also called again for str1 and str2 constructs. The above code, using the Compile command is: g++-fno-elide-constructors-o rvo rvo.cpp

The-fno-elide-constructors option cancels the compiler's copy-elision optimization policy. The results are as follows:

Constructor is called! this->_data:8949776

Copy Constructor is called! src:8949776 dst:8949808

Deconstructor is called! this->_data:8949776

Deconstructor is called! this->_data:8949808

--------------------

Constructor is called! this->_data:8949808

Copy Constructor is called! src:8949808 dst:8949776

Deconstructor is called! this->_data:8949808

Deconstructor is called! this->_data:8949776

--------------------

Constructor is called! this->_data:8949776

Copy Constructor is called! src:8949776 dst:8949808

Deconstructor is called! this->_data:8949776

Copy Constructor is called! src:8949808 dst:8949776

Deconstructor is called! this->_data:8949808

--------------------

Constructor is called! this->_data:8949808

Copy Constructor is called! src:8949808 dst:8949840

Deconstructor is called! this->_data:8949808

Copy Constructor is called! src:8949840 dst:8949808

Deconstructor is called! this->_data:8949840

--------------------

Deconstructor is called! this->_data:8949808

Deconstructor is called! this->_data:8949776

If the-fno-elide-constructors option is removed at compile time, the compiler turns on Rvo and the result is as follows:

Constructor is called! this->_data:34054160

Deconstructor is called! this->_data:34054160

--------------------

Constructor is called! this->_data:34054160

Deconstructor is called! this->_data:34054160

--------------------

Constructor is called! this->_data:34054160

--------------------

Constructor is called! this->_data:34054192

--------------------

Deconstructor is called! this->_data:34054192

Deconstructor is called! this->_data:34054160

When Rvo is turned on, an unnecessary copy is omitted, and after Rvo is turned on, the function directly constructs the object directly where it receives the return value.

In fact, foo1 and Foo2 correspond to Rvo and Nrvo respectively (Named Return Value optimization). Named return value optimization (NRVO) is the same as the optimization method when returning a "named Object" (that is, a variable with a name) by value, but the situation is much more complicated because the returned value is a named variable. Therefore, the conditions to perform the optimization are more stringent. For example, a function that returns an object of different names on a different return path does not execute nrvo.

For example, the following code:

MyString bar1 (int n) {    if (n > 2)    {        return MyString ("abc");    }    else    {        return MyString ("ABC");}    } MyString bar2 (int n) {    MyString str1 ("abc");    MyString str2 ("ABC");    if (n > 2)    {        return str1;    }    else    {        return str2;}    } int main (int argc, char **argv) {    bar1 (1);    cout << "--------------------\ n";    BAR2 (1);    cout << "--------------------\ n";    MyString str1 = bar1 (1);    cout << "--------------------\ n";    MyString str2 = bar2 (1);    cout << "--------------------\ n";    return 0;}

The function Bar1 returns the temporary object, BAR2 returns the named object, that is, if the optimization is performed, BAR1 executes Rvo and BAR2 executes Nrvo.

The first is the result of running with the-fno-elide-constructors option:

Constructor is called! this->_data:11149328

Copy Constructor is called! src:11149328 dst:11149360

Deconstructor is called! this->_data:11149328

Deconstructor is called! this->_data:11149360

--------------------

Constructor is called! this->_data:11149360

Constructor is called! this->_data:11149328

Copy Constructor is called! src:11149328 dst:11149392

Deconstructor is called! this->_data:11149328

Deconstructor is called! this->_data:11149360

Deconstructor is called! this->_data:11149392

--------------------

Constructor is called! this->_data:11149392

Copy Constructor is called! src:11149392 dst:11149360

Deconstructor is called! this->_data:11149392

Copy Constructor is called! src:11149360 dst:11149392

Deconstructor is called! this->_data:11149360

--------------------

Constructor is called! this->_data:11149360

Constructor is called! this->_data:11149328

Copy Constructor is called! src:11149328 dst:11149424

Deconstructor is called! this->_data:11149328

Deconstructor is called! this->_data:11149360

Copy Constructor is called! src:11149424 dst:11149360

Deconstructor is called! this->_data:11149424

--------------------

Deconstructor is called! this->_data:11149360

Deconstructor is called! this->_data:11149392

After adding the-fno-elide-constructors option, the result is as follows:

Constructor is called! this->_data:9449488

Deconstructor is called! this->_data:9449488

--------------------

Constructor is called! this->_data:9449488

Constructor is called! this->_data:9449520

Copy Constructor is called! src:9449520 dst:9449552

Deconstructor is called! this->_data:9449520

Deconstructor is called! this->_data:9449488

Deconstructor is called! this->_data:9449552

--------------------

Constructor is called! this->_data:9449552

--------------------

Constructor is called! this->_data:9449488

Constructor is called! this->_data:9449520

Copy Constructor is called! src:9449520 dst:9449584

Deconstructor is called! this->_data:9449520

Deconstructor is called! this->_data:9449488

--------------------

Deconstructor is called! this->_data:9449584

Deconstructor is called! this->_data:9449552

In contrast to the above results, the call to return the BAR1 function of the temporary object is optimized. The invocation of the BAR2 function, regardless of whether there is a-fno-elide-constructors option, calls Bar2 to return the same result, stating that Nrvo is not executed. Contrast "MyString str2 = bar2 (1);" The result of the execution of the statement, it was found that after adding the-fno-elide-constructors option option, the call to the copy constructor was reduced only once because, although Bar2 did not perform Nrvo, the STR2 was initialized with the temporary object returned by BAR2. The compiler still has a copy elision optimization strategy.

The explanation for copy elision is as follows:

In C + + computer programming, copy elision refers to a compiler optimization technique that eliminates unnecessary copying of objects.

The standard also describes a few situations where copying can is eliminated even if this would alter the program ' s Behavi Or, the most common being the return value optimization. Another widely implemented optimization, described in the C + + standard, was when a temporary object of class type is copied To an object of the same type.

(https://en.wikipedia.org/wiki/Copy_elision)

When a nameless temporary, not bound to any references, would is copied or moved (since c++11) into an object of T He same type (ignoring top-level cv-qualification), the Copy/move (since c++11) is omitted. when that's temporary is constructed, it's constructed directly in the storage where it would otherwise be copied or m Oved (since c++11) to. When the nameless temporary are the argument of a return statement, this variant of copy elision is known as RVO, "return V Alue optimization ".

(http://en.cppreference.com/w/cpp/language/copy_elision)

Note: The compilation environment for all of the above codes is: Operating system CentOS Linux release 7.3.1611;GCC version: GCC version 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)

Reference:

http://blog.csdn.net/gatieme/article/details/22650353

Http://www.cnblogs.com/liyiwen/archive/2009/12/02/1615711.html

C + + return value optimization

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.