成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Visual Studio:優化了復制/移動省略

開發 前端
當 C++ 函數中的 return 關鍵字后跟非內置類型的表達式時,執行該 return 語句會將表達式的結果復制到調用函數的返回槽(Return Slot)中。為此,將調用非內置類型的復制或移動構造函數。然后,作為退出函數的一部分,將調用函數局部變量的析構函數,可能包括 return 關鍵字后面的表達式中命名的任何變量。

蝎子

為了能發文,標題中的復制/移動省略是 Copy/Move Elision 的硬翻譯,請各位大大海涵。下文中我會同時使用這兩種術語。

Visual Studio 中 Copy/Move Elision 的變化

在 Visual Studio 2022 版本 17.4 預覽版 3 中,我們顯著增加了適用于Copy/Move Elision 情況的數量,并讓用戶能夠更好地控制是否啟用這些轉換。

Copy/Move Elision 是什么?

當 C++ 函數中的 return 關鍵字后跟非內置類型的表達式時,執行該 return 語句會將表達式的結果復制到調用函數的返回槽(Return Slot)中。為此,將調用非內置類型的復制或移動構造函數。然后,作為退出函數的一部分,將調用函數局部變量的析構函數,可能包括 return 關鍵字后面的表達式中命名的任何變量。

C++ 規范允許編譯器直接在調用函數的返回槽中構造返回的對象,從而省略作為返回的一部分執行的復制或移動構造函數。與大多數其他優化不同,這種轉換允許對程序的輸出產生可觀察的影響 – 即復制或移動構造函數以及關聯的析構函數可以少調用一次。

Visual Studio 中的 Copy/Move Elision

C++ 標準要求在將返回值初始化為 return 語句的一部分時(例如,當返回類型為 Foo 的函數返回返回 Foo()時),編譯器需要執行 Copy/Move Elision。Microsoft Visual C++ 編譯器始終根據需要對返回語句執行 Copy/Move Elision,而不管傳遞給編譯器的標志如何。此行為保持不變。

在 Visual Studio 17.4 預覽版 3 中對可選 Copy/Move Elision 的更改

當返回的值為命名變量時,編譯器可能會省略復制或移動,但不是必需的。C++ 標準仍要求為命名的返回變量定義復制或移動構造函數,即使編譯器在所有情況下都省略了構造函數。在 Visual Studio 2022 版本 17.4 預覽版 3 之前,當禁用優化(例如使用 /Od 編譯器標志或使用了 #pragma optimize(“”,off))時,編譯器將僅執行強制Copy/Move Elision。使用 /O2 標志,編譯器將通過簡單的控制流為優化的函數執行可選的Copy/Move Elision。

從 Visual Studio 2022 版本 17.4 預覽版 3 開始,我們為開發人員提供了與新的 /Zc:nrvo 編譯器標志保持一致的選項。默認情況下,當使用 /O2 標志、/permissive- 編譯代碼時,或者在為 /std:c++20 或更高版本進行編譯時,將傳遞 /Zc:nrvo 標志。通過此標志后,將盡可能執行復制和移動省略。我們希望在將來的版本中默認啟用 /Zc:nrvo。另外,開發者還可以使用 /Zc:nrvo- 標志顯式禁用可選的Copy/Move Elision。請注意,無法禁用強制型的Copy/Move Elision。

在 Visual Studio 2022 版本 17.4 預覽版 3 中,當使用 /Zc:nrvo、/O2、/permissive-或 /std:c++20 或更高版本的標志啟用可選復制/移動省略時,我們還增加了Copy/Move Elision的位置。

可選 Copy/Move Elision 的示例

可選 Copy/Move Elision 的最簡單示例是以下函數:Foo SimpleReturn() {Foo result;return result;}

在這種情況下,如果傳遞了 /O2 標志,則早期版本的 MSVC 編譯器已將結果的復制或移動到返回槽中。在 Visual Studio 2022 版本 17.4 預覽版 3 中,如果傳遞了 /permissive-、/std:c++20 或更高版本或 /Zc:nrvo 標志,也會省略復制或移動,如果傳遞了 /Zc:nrvo- 標志,則保留復制或移動。

從 Visual Studio 2022 版本 17.4 預覽版 3 開始,如果將 /O2、/permissive-、/std:c++20 或更高版本或 /Zc:nrvo 標志傳遞給編譯器,而 /Zc:nrvo- 標志未傳遞到編譯器,我們現在在以下其他情況下執行復制/移動省略。

在循環中返回

Foo ReturnInALoop(int iterations) {for (int i = 0; i < iterations; ++i) {Foo result;if (i == (iterations / 2)) {return result;}}}結果對象將在循環的每次迭代開始時正確構造,并在每次迭代結束時銷毀。在返回結果的迭代中,退出函數時不會調用其析構函數。當返回的對象超出該函數的范圍時,函數的調用方將銷毀該對象。

在異常處理中返回

Foo ReturnInTryCatch() {
try {
Foo result;
return result;
} catch () {}
}

如果傳遞了 /O2、/permissive-、/std:c++20 或更高版本,或者傳遞了 /Zc:nrvo 標志,而 /Zc:nrvo- 標志未傳遞,則結果對象的復制或移動現在將被省略。我們現在還可以妥善處理更復雜的情況,例如:

int n;

void throwFirstThreeIterations() {
++n;
if (n <= 3) throw n;
}

Foo ComplexTryCatch()
{
Label1:
Foo result;

try {
throwFirstThreeIterations();
return result;
}
catch() {
goto Label1;
}
}

結果對象將在調用方函數的返回槽中構造,并且在成功返回時不會為其調用復制/移動構造函數或析構函數。引發異常時,是否析構結果對象取決于向編譯器傳遞哪些異常處理標志。默認情況下,不會發生堆棧展開,因此不會調用析構函數。但是,如果使用 /EHs、/EHa 或 /EHr 標志啟用了堆棧展開異常處理,則 goto Label1 將導致調用結果的析構函數,因為它跳轉到初始化結果之前。無論哪種方式,當再次到達表達式 Foo 結果時,將在返回槽中再次構造對象。

復制具有默認參數的構造函數

現在,我們可以正確檢測到具有默認參數的復制或移動構造函數仍然是復制或移動構造函數,因此可以在上述情況下被省略。具有默認參數的復制構造函數如下所示:structStructWithCopyConstructorDefaultParam {int X;

struct
StructWithCopyConstructorDefaultParam {
int X;

StructWithCopyConstructorDefaultParam(int x) : X(x) {}
StructWithCopyConstructorDefaultParam(StructWithCopyConstructorDefaultParam const& original, int defaultParam = 0) :
X(original.X + defaultParam) {
printf(“Copy constructor called.\n”);
}
};

對NRVO的限制

盡管 MSVC 編譯器現在在更多情況下執行Copy/Move Elision,但并不總是能夠執行它。若要了解為什么會這樣,請考慮以下函數:

Foo WhichShouldIReturn(bool condition) {
Foo resultA;
if (condition) {
Foo resultB;
return resultB;
}
return resultA;
}

復制省略構造要在返回槽中返回的對象,但在這種情況下,應在返回槽中構造哪個對象?為了在返回結果A時省略結果A的副本,必須在返回槽中構造它。但是,如果條件為真,則需要在銷毀結果 A 之前在返回槽中構造結果 B。無法對兩個路徑執行復制省略。

我們目前選擇避免在函數中的所有路徑上執行可選的Copy/Move Elision,如果在任何路徑上它是不可能的的話。但是,對內聯決策、死代碼消除和其他優化的更改可能會更改Copy/Move Elision的可能性。因此,編寫依賴于命名變量的Copy/Move Elision的某些行為的代碼是不安全的,除非使用 /Zc:nrvo- 禁用了所有可選的Copy/Move Elision。

只要啟用了堆棧展開異常處理或未引發異常,仍然可以安全地假定每個構造函數調用都有匹配的析構函數調用。

總結

寫著舊時代的 C++,一直都為如何高性能地返回一個對象發愁。沒錯,正是在下。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2013-05-17 09:31:53

Windows AzuOffice 365Visual Stud

2009-05-11 09:45:23

Visual Stud復制代碼ID

2021-10-20 10:12:19

開發Visual Stud圖標

2009-06-23 10:36:32

移動開發isual Studi

2023-09-05 07:32:22

vscode開源故障

2013-11-14 01:09:35

微軟Visual StudVisual Stud

2009-12-02 09:43:38

Visual Stud

2024-02-27 12:42:38

開發前端

2019-09-19 08:00:00

Visual StudVisual Stud編程語言

2009-11-10 10:24:28

Visual Stud

2009-11-23 15:41:44

Visual Stud

2009-11-23 17:12:20

Visual Stud

2009-11-10 13:43:37

Visual Stud

2020-08-12 09:53:18

代碼開發工具

2019-08-13 09:30:50

編程C++后端

2009-11-06 13:25:35

Visual Stud

2009-11-10 12:44:01

Visual Stud

2010-02-22 16:43:33

Visual Stud

2009-11-12 12:42:35

Visual Stud

2010-12-14 09:15:50

Visual Stud
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美在线国产精品 | 中文字幕国产精品视频 | 亚洲色图综合 | 91成人午夜性a一级毛片 | 成人国产精品免费观看视频 | 日韩成人专区 | 日韩人体视频 | 91视频在线观看免费 | 亚洲综合在 | 欧美黑人国产人伦爽爽爽 | 亚洲香蕉| 色花av| 国产精品久久 | 中文字幕一区二区三区精彩视频 | 国产成人99久久亚洲综合精品 | 久久精品综合网 | 日韩三级一区 | 夜夜爽99久久国产综合精品女不卡 | 天天操夜夜看 | 91久久精品国产91久久性色tv | 欧美黄色一区 | 尤物在线精品视频 | 欧美一区| 亚洲成人一区二区 | 中文字幕在线观看视频一区 | 在线欧美 | 亚洲国产成人av | 国产一区二区三区久久久久久久久 | 毛片综合 | 亚洲精品黄 | 久草新在线 | 亚洲精品一区二区网址 | 成人精品国产一区二区4080 | 夜夜爽99久久国产综合精品女不卡 | 午夜影院在线观看 | 男女那个视频 | 国产ts人妖系列高潮 | 午夜精品久久久久久久久久久久久 | 你懂的在线视频播放 | 一区二区久久精品 | 色吊丝2288sds中文字幕 |