[英]Reduce Copy Constructor Calls
以下代碼是我正在處理的項目中的一個最小示例。 主要問題是我想減少對復制構造函數的調用次數,但我不清楚這樣做的正確方法。
#include<iostream>
class MyClass
{
public:
MyClass() {std::cout << "Default Constructor\n";}
MyClass(const MyClass &input) {std::cout << "Copy Constructor\n";}
MyClass & operator=(const MyClass &input)
{std::cout << "Assignment\n"; return *this;}
MyClass & operator+=(const MyClass &input) {return *this;}
friend MyClass operator+(MyClass lhs,const MyClass &);
};
MyClass operator+(MyClass lhs,const MyClass &rhs)
{lhs+=rhs;return lhs;}
int main()
{
MyClass a,b,c;
c=a+b;
return 0;
}
當我運行代碼時,輸出是:
Default Constructor
Default Constructor
Default Constructor
Copy Constructor
Copy Constructor
Assignment
三個默認構造函數在 a、b 和 c 的構造中被調用。
這兩個復制構造函數在 operator+ 中的第一個參數和 operator+ 的返回值中被調用。
賦值將 a+b 賦值給 c 的結果賦值。
主要問題:在我的應用程序中,復制構造函數很昂貴(它涉及內存分配)。 另一方面,分配相對便宜。 減少對復制構造函數的調用的正確方法是什么?
我考慮了一些解決方案,但沒有一個讓我高興:
據我了解,從閱讀中可以看出,operator+ 不應該有第一個參數的引用,因為這有助於鏈接臨時變量。 因此,這種復制構造函數似乎是不可避免的。
以下代碼明顯更快(由於沒有復制構造函數調用): c = a; c += b;
c = a; c += b;
我可以使用這種格式編寫代碼,但這需要更精細的方法。 我希望編譯器比我自己做這些調整更聰明。
我可以實現一個函數add(MyClass &,const MyClass &,const MyClass &);
但這失去了使用加法運算符的便利性(並且由於我使用的不同數據類型的數量而需要大量(無意識的)編碼)。
我已經查看了這些問題,但在這種情況下我沒有看到任何可能提高性能的建議:
復制構造函數調用兩次, 復制構造函數調用兩次, 復制省略條件
對評論的回應:
私有數據包括 MPFR's 和 MPFI's,構造函數包括該數據的初始化。 也許構造函數的不同實現是合適的,但我不確定。
我考慮過移動構造函數,但有時我也需要復制副本分配。 從cppreference看來,這些不能共存(或者至少當我一開始嘗試時出現錯誤)。 看來這應該是最好的選擇。
您正在通過副本傳遞lhs
。 這就是為什么你有額外的復制構造函數調用。 修改您的operator+
:
MyClass operator+(const MyClass &lhs, const MyClass &rhs)
為了盡量減少復制構造函數調用,我建議您定義移動構造函數並完美轉發您的運算符參數。 移動構造函數:
MyClass(MyClass &&input) {std::cout << "Move Constructor\n";}
完美轉發運營商:
template<typename T>
friend MyClass operator+(T &&lhs,T &&rhs) {return std::forward<T>(lhs);}
通過正確的調用,您的運算符將涉及移動構造函數而不是復制構造函數。 例如,如果您添加來自函數的對象並立即存儲結果(例如MyClass c=a+b;
而不是MyClass c;c=a+b;
),由於RVO,您可以保存復制構造函數。
假設您有一個返回MyClass
實例的函數:
MyClass something() {return MyClass();}
如果添加函數返回值並立即存儲它們,例如:
MyClass c=something()+something();
那么就不會涉及復制構造函數。
我在這里放了一系列示例,其中我將const MyClass&
參數與operator+
並將完美轉發參數與operator-
。 您可以看到它在最后一個示例中有所不同,但在所有其他示例中沒有。 這就是為什么我說“用正確的電話”。 如果您必須操縱可以像這樣轉發的對象,則可能值得一試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.