程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> clang++ 優化返回代碼

clang++ 優化返回代碼

編輯:C++入門知識

clang++ 優化返回代碼


clang++會自動優化函數返回代碼,無論是c++11標准還是之前的標准。下面是例子:

注意,clang++ 3.5默認編譯選項不是c++11

 

 c++ --version
Ubuntu clang version 3.5.0-4ubuntu2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix

無論是C++11與否,下面的代碼輸出地址都是相同:

 

 

class A {
    public:
      A() {
        cout << ctor << endl;
      }

      A(A const& src) {
        cout << copy << endl;
      }

      A & operator = (A const& src) {
        cout << = << endl;
        return *this;
      }
    };

    A test() {
      A a;
      cout << &a << endl;
      return a;
    }

    int main(int argc, char ** argv) {
      try {
        A a2 = test();
        cout << &a2 <

 

輸出為:

ctor
0x7ffd4ed29998
0x7ffd4ed29998

 

在test函數中一個有趣的現象是,當沒有啟動c++11編譯選項,這裡是依靠clang++編譯器的自動優化技術。當啟動了c++11選項後,代碼沒有發生任何變化,但是已經使用了move語義。

 

我在前幾天的程序中當用這種情況的時候返回vector,遇到了core dump,換成了vector & output參數的方式得以解決。還需要進一步追蹤,是否是clang++ 3.5的bug。

 

下面是stackoverflow上的一個討論貼,比較有價值:

 

246 down vote accepted

First example

std::vector return_vector(void)
{
    std::vector tmp {1,2,3,4,5};
    return tmp;
}

std::vector &&rval_ref = return_vector();

The first example returns a temporary which is caught by rval_ref. That temporary will have its life extended beyond the rval_ref definition and you can use it as if you had caught it by value. This is very similar to the following:

const std::vector& rval_ref = return_vector();

except that in my rewrite you obviously can't use rval_ref in a non-const manner.

Second example

std::vector&& return_vector(void)
{
    std::vector tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector &&rval_ref = return_vector();

In the second example you have created a run time error. rval_ref now holds a reference to the destructed tmp inside the function. With any luck, this code would immediately crash.

Third example

std::vector return_vector(void)
{
    std::vector tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector &&rval_ref = return_vector();

Your third example is roughly equivalent to your first. The std::move on tmp is unnecessary and can actually be a performance pessimization as it will inhibit return value optimization.

The best way to code what you're doing is:

Best practice

std::vector return_vector(void)
{
    std::vector tmp {1,2,3,4,5};
    return tmp;
}

std::vector rval_ref = return_vector();

I.e. just as you would in C++03. tmp is implicitly treated as an rvalue in the return statement. It will either be returned via return-value-optimization (no copy, no move), or if the compiler decides it can not perform RVO, then it will use vector's move constructor to do the return. Only if RVO is not performed, and if the returned type did not have a move constructor would the copy constructor be used for the return.

shareeditflag answered Feb 13 '11 at 20:52 Howard Hinnant
74.1k12145251   6       Great thanks for the elaborated answer ! – Tarantula Feb 14 '11 at 17:10 10       Compilers will RVO when you return a local object by value, and the type of the local and the return of the function are the same, and neither is cv-qualified (don't return const types). Stay away from returning with the condition (:?) statement as it can inhibit RVO. Don't wrap the local in some other function that returns a reference to the local. Just return my_local;. Multiple return statements are ok and will not inhibit RVO. – Howard Hinnant Feb 25 '13 at 20:18 3       There is a caveat: when returning a member of a local object, the move must be explicit. – boycy Feb 26 '13 at 8:58 4       @NoSenseEtAl: There is no temporary created on the return line. move doesn't create a temporary. It casts an lvalue to an xvalue, making no copies, creating nothing, destroying nothing. That example is the exact same situation as if you returned by lvalue-reference and removed the move from the return line: Either way you've got a dangling reference to a local variable inside the function and which has been destructed. – Howard Hinnant Feb 27 '13 at 16:11 1 upvote   flag Just a nit: Since you named the variable (tmp) in the Best practice section, it is the NRVO that kicks in, not the RVO. These are two different optimizations. Other than that, great answer! – Daniel Frey Feb

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved