设为首页 加入收藏

TOP

clang++ 优化返回代码(一)
2015-11-21 01:05:08 来源: 作者: 【 】 浏览:6
Tags: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 sa
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇leetcode:Rotate List 下一篇UVA - 11464 - Even Parity

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: