我想知道為什么 C std::optional<T>在回傳時不執行 RVO T。IE,
struct Bar {};
std::optional<Bar> get_bar()
{
return Bar{}; // move ctor of Bar called here
// instead of performing RVO
}
Bar get_bar2()
{
return Bar{}; // NO move ctor called
// RVO performed
}
std::optional<Bar> get_bar_rvo()
{
std::optional<Bar> opt;
opt.emplace();
return opt; // NO move ctor called
// ROV performed
}
在上述情況下,get_bar2執行 RVO 而不get_bar執行。
多一點提示,編譯器就可以優化get_bar_rvo,但代碼會變得更長更煩人。
從參考中,我了解到get_bar不符合“強制省略復制/移動操作”的要求
在物件的初始化中,當初始化運算式是與變數型別具有相同型別別(忽略 cv 限定)的純右值時:
由于std::optional<T>和T不是同一個型別別,所以RVO不是強制的。
但是,我認為執行 RVOstd::optional<T>應該非常容易并且非常有用,而不需要手動撰寫更長的代碼作為get_bar_rvo.
為什么我的編譯無法識別和優化get_barjust like get_bar2?
環境:MacOS
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
編譯為-std=c 17 -O3
uj5u.com熱心網友回復:
get_bar_rvo不執行RVO,它執行NRVO(命名回傳值優化)。這是無法保證的。
對于,您可以將其留給使用或其就地建構式 (6)get_bar,而不是自己構造:Barstd::optionalstd::make_optional
std::optional<Bar> get_bar()
{
return std::make_optional<Bar>();
// or return std::optional<Bar>(std::in_place);
}
這會按預期執行 RVO。
uj5u.com熱心網友回復:
get_bar()回傳std::optional<Bar>,并且沒有std::optional<Bar>像預期的那樣被復制或移動。
Bar被移動到,std::optional<Bar>因為您創建了一個臨時檔案Bar,然后請求std::optional<Bar>從它構造。它與 RVO 或 NRVO 無關。它是關于將物件傳遞給函式。
我們不希望在任何舊函式呼叫(如 )中消除移動foo(Bar{}),std::optional建構式也不例外。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/535459.html
