[英]C++ Is there something like RVO for passing temporary objects to functions?
使用RVO可以從返回的對象創建對象,而無需移動或復制。 將對象傳遞給函數時,是否可以做類似的事情?
class SomeClass {
int a;
public:
SomeClass(int _a) {a = _a; std::cout << "created\n";}
SomeClass(const SomeClass& source) {a = source.a; std::cout << "copied\n";}
SomeClass(SomeClass&& source) {a = source.a; std::cout << "moved\n";}
};
void create(SomeClass&& source) {
SomeClass some_object( std::move( source));
//p_some_object = new SomeClass( std::move( source));
//new( p_some_object) SomeClass( std::move( source));
}
// ...
create(SomeClass(15));
在此示例中,結果是“創建,移動”。 (GCC 5.4 / C ++ 11 / -O3)與new或place-new相同。 沒有分支或任何分支,那么為什么不移動就不能創建它?
無法保證編譯器必須進行內聯和分析,以識別出由source
引用的臨時對象是不必要的。 除此之外,甚至RVO也用於值語義。 當&&
引用起作用時,不能保證。
碰巧的是,如果您遵循C ++函數參數的一般規則,那么GCC可以很好地處理您的情況: “如果仍然需要復制參數,請按值接受參數。”
按值接受表示在這種情況下將參數構造為調用的一部分的情況下,不需要復制或移動(在GCC上可以是“ RVO” -ed)。
class SomeClass {
int a;
public:
SomeClass(int _a) {a = _a; std::cout << "created\n";}
SomeClass(const SomeClass& source) {a = source.a; std::cout << "copied\n";}
SomeClass(SomeClass&& source) {a = source.a; std::cout << "moved\n";}
};
void create(SomeClass some_object) {
}
int main() {
create(SomeClass(15));
}
如果嘗試使用 ,則僅顯示created
消息。
如果目標是create
以為您構造對象,則使用帶有參數轉發功能的模板化函數,以便在create
內構造它,例如
template<typename T, class... Args>
T create(Args&&... args) {
T some_object(std::forward<Args>(args)...);
return some_object;
}
int main() {
auto foo = create<SomeClass>(15);
}
它通過傳遞構造函數參數作為轉發引用來解決問題,並在create
內部構造對象本身,避免了任何額外的構造, 如此處所示 。
RVO不會與引用一起發生,也不會在通過函數參數創建另一個對象時發生。
如果將引用參數更改為值參數,則會將RVO應用於它,而不是本地對象:
void create(SomeClass source) {
SomeClass otherObject = std::move(source); // No RVO, object constructed from parameter
}
// ...
create(SomeClass{15}); // RVO applied to source parameter
但是,您可以使用lambda作為函數參數來實現它:
template<typename C>
void create(C source) {
SomeClass some_object{source()};
}
// ...
create([]{ return SomeClass{15}; });
您可以檢查實時輸出
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.