copy elison RVO NRVO
藍色的博文
To summarize, RVO is a compiler optimization technique, while std::move is just an rvalue cast, which also instructs the compiler that it's eligible to move the object. The price of moving is lower than copying but higher than RVO, so never apply std::move to local objects if they would otherwise be eligible for the RVO.
因此,在能夠使用copy elision時,我們不要在return時加std::move()。在copy elision不work時,我們還是要加上std::move()從而調(diào)用move constructor而不是調(diào)用copy constructor.
博文中比較費解的是最后一個示例,這么寫似乎產(chǎn)生了bug。
個人理解:最后一個示例觸發(fā)了RVO,導(dǎo)致第一次拷貝:棧內(nèi)變量拷貝至返回值臨時變量被省略(兩次拷貝參見下文),第二次拷貝:臨時變量拷貝至具名變量未省略。而因為變量類型是右值引用,第二次的拷貝變成了移動構(gòu)造。于是就出現(xiàn)了奇怪的輸出。
Copy elision
In general, the C++ standard allows a compiler to perform any optimization, provided the resulting executable exhibits the same observable behaviour as if (i.e. pretending) all the requirements of the standard have been fulfilled. This is commonly referred to as the "as-if rule".[8] The term return value optimization refers to a special clause in the C++ standard that goes even further than the "as-if" rule: an implementation may omit a copy operation resulting from a return statement, even if the copy constructor has side effects.[1]
The following example demonstrates a scenario where the implementation may eliminate one or both of the copies being made, even if the copy constructor has a visible side effect (printing text).[1] The first copy that may be eliminated is the one where a nameless temporary C could be copied into the function f's return value. The second copy that may be eliminated is the copy of the temporary object returned by f to obj.
#include <iostream>struct C {C() {}C(const C&) { std::cout << "A copy was made.\n"; } };C f() {return C(); }int main() {std::cout << "Hello World!\n";C obj = f();return 0; }Depending upon the compiler, and that compiler's settings, the resulting program may display any of the following outputs:
Hello World! A copy was made. A copy was made. Hello World! A copy was made. Hello World!這里有一篇博文,結(jié)合了《深度探索C++對象模型》,博文鏈接。
在g++中開啟選項-fno-elide-constructors可以去掉任何返回值優(yōu)化,則C obj = f(); 中,會發(fā)生兩次拷貝,f()內(nèi)棧內(nèi)變量拷貝構(gòu)造返回值臨時變量,返回值臨時變量拷貝構(gòu)造obj變量。
這里有一份更詳細(xì)點的文檔...
https://en.cppreference.com/w/cpp/language/copy_elision
===============================================================
最后是關(guān)于push_back與emplace_back的測試。
T &&var1 = std::move(var2); 不存在移動拷貝。
template< class... Args >void emplace_back( Args&&... args );通過std::forward<Args>(args)...實現(xiàn)。 1 #include <bits/stdc++.h> 2 using namespace std; 3 struct Stu { 4 int age; 5 Stu(const int age = 0):age(age) { 6 cout << "construct" << endl; 7 } 8 Stu(const Stu& s){ 9 cout << "copy construct" << endl; 10 } 11 Stu(Stu&& s) { 12 cout << "move construct" << endl; 13 }; 14 Stu& operator = (const Stu& s) { 15 cout << "operator construct" << endl; 16 } 17 ~Stu(){ 18 cout << "destruct" << endl; 19 } 20 }; 21 22 Stu Init(const int age) { 23 return Stu(age); 24 } 25 26 int main() { 27 Stu s1(26); 28 cout << "1--------------" << endl; 29 Stu s2 = Init(20); 30 cout << "2--------------" << endl; 31 vector<Stu> ve; 32 ve.reserve(10); 33 cout << "3--------------" << endl; 34 ve.push_back(s1); 35 cout << "4--------------" << endl; 36 Stu&& ss = std::move(s1); 37 ve.push_back(std::move(s1)); 38 cout << "5--------------" << endl; 39 ve.emplace_back(Stu(3)); 40 cout << "6--------------" << endl; 41 ve.emplace_back(3); 42 return 0; 43 } 44 45 /* 46 construct 47 1-------------- 48 construct 49 move construct 50 destruct 51 move construct 52 destruct 53 2-------------- 54 3-------------- 55 copy construct 56 4-------------- 57 move construct 58 5-------------- 59 construct 60 move construct 61 destruct 62 6-------------- 63 construct 64 destruct 65 destruct 66 destruct 67 destruct 68 destruct 69 destruct 70 */ View Code
?
轉(zhuǎn)載于:https://www.cnblogs.com/dirge/p/10389996.html
總結(jié)
以上是生活随笔為你收集整理的copy elison RVO NRVO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每日一程-10.五种基本随机数测试-续
- 下一篇: [Swift]LeetCode513.