C++筆記-編譯優化:RVO、NRVO


C++編譯器優化技術:RVO、NRVO和復制省略: https://www.cnblogs.com/kekec/p/11303391.html
C++中的RVO和NRVO:https://blog.csdn.net/yao_zou/article/details/50759301
詳解RVO與NRVO(區別於網上常見的RVO) https://blog.csdn.net/virtual_func/article/details/48709617
RVO和NRVO的區別是什么?: https://www.zhihu.com/question/29511959

RVO和NRVO

RVO (return value optimization), 返回值優化,簡稱RVO,是編譯器的一項優化技術,它涉及(功能是)消除為保存函數返回值而創建的臨時對象。
NRVO (named return value optimization),NRVO的優化比RVO 的優化更進一步,直接將要初始化的對象替代掉返回的局部對象進行操作。

#include <stdio.h>
class Object {
 public:
  Object() { printf("%p construct\n", this); }

  Object(const Object& cp) { printf("%p copy construct\n", this); }
  ~Object() { printf("%p destruct\n", this); }
};

Object getObjRVO() {
  return Object();  // RVO
}

Object getObjNRVO() {
  Object localObj;
  return localObj;  // NRVO
}

int main() {
  printf("rvo:\n");
  { auto a = getObjRVO(); }
  printf("nrvo:\n");
  { auto b = getObjNRVO(); }                                                                                           
  return 0;
}
// https://www.zhihu.com/question/32237405/answer/55440484

編譯:g++ test_rvo.cpp -o test
執行結果:

rvo:
0x7ffe558ff9de construct
0x7ffe558ff9de destruct
nrvo:
0x7ffe558ff9df construct
0x7ffe558ff9df destruct

增加編譯選項 -fno-elide-constructors
編譯:g++ test_rvo.cpp -o test -fno-elide-constructors
執行結果:

rvo:
0x7ffe3197775f construct            // getObj 內部構造臨時對象
0x7ffe3197778e copy construct    // return時,調用復制構造函數構造返回值
0x7ffd9de82f8f destruct              // 析構getObj內部的臨時對象
0x7ffd9de82fbd copy construct    // main函數內利用Object的拷貝構造函數構造對象a
0x7ffd9de82fbe destruct             // 析構返回值
0x7ffd9de82fbd destruct             // 析構對象a
nrvo:
0x7ffd9de82f8f construct
0x7ffd9de82fbf copy construct
0x7ffd9de82f8f destruct
0x7ffd9de82fbc copy construct
0x7ffd9de82fbf destruct
0x7ffd9de82fbc destruct

-fno-elide-constructors 編譯選項釋義:

The C++ standard allows an implementation to omit creating a temporary that is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.
C++ 標准允許實現省略創建僅用於初始化相同類型的另一個對象的臨時對象。 指定此選項會禁用該優化,並強制 g++ 在所有情況下調用復制構造函數。

增加轉移構造函數

class Object {
 public:
  Object() { printf("%p construct\n", this); }
  Object(const Object& cp) { printf("%p copy construct\n", this); }
  Object(Object&& cp) { printf("%p move construct\n", this); }                                                         
  ~Object() { printf("%p destruct\n", this); }
};

編譯:g++ test_rvo.cpp -o test -fno-elide-constructors
執行結果:

rvo:
0x7ffd42717a2f construct
0x7ffd42717a5e move construct
0x7ffd42717a2f destruct
0x7ffd42717a5d move construct
0x7ffd42717a5e destruct
0x7ffd42717a5d destruct
nrvo:
0x7ffd42717a2f construct
0x7ffd42717a5f move construct
0x7ffd42717a2f destruct
0x7ffd42717a5c move construct
0x7ffd42717a5f destruct
0x7ffd42717a5c destruct

發現沒有再調用拷貝構造函數,而是調用的轉移構造函數

RVO 和std::move對比

增加getObjNRVOMove方法

Object getObjNRVOMove() {
  Object localObj;
  return std::move(localObj);  // NRVO
}

int main() {
  printf("nrvo move:\n");
  { auto b = getObjNRVOMove(); }                                                                                       
  return 0;
}

編譯:g++ test_rvo.cpp -o test
執行結果:

nrvo move:
0x7ffc75a6a0ef construct
0x7ffc75a6a11d move construct
0x7ffc75a6a0ef destruct
0x7ffc75a6a11d destruct

可見RVO/ NRVO和std::move可同時生效


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM