假設我有以下代碼。
class A
{
public:
float x, y, z;
A(float x, float y, float z) : x(x), y(y), z(z) {}
};
float average(A a)
{
return (a.x a.y a.z) / 3;
}
以這兩種方式呼叫函式之間有什么實際區別嗎?
// a)
average(A(1, 2, 3))
// b)
average({1, 2, 3})
uj5u.com熱心網友回復:
這取決于您使用的 C 版本。
從copy elision @cpprefrence復制(并稍加修改)(因此,不是確切的參考):
在 C 17 中,核心語言規范
prvalues和臨時檔案與早期的 C 修訂版根本不同:不再有臨時檔案可以復制/移動。
這意味著從 C 17 開始,不允許復制或移動A您直觀顯示的臨時檔案。average(A(1, 2, 3))其實沒有暫時的。在 C 17 之前,大多數編譯器使用復制(和移動)省略(之前也允許,但不是強制性的)來達到相同的效果 - 但您不能可移植地依賴它。
在 C 17 中,這種形式的復制省略是強制性的,因此稱為回傳值優化,或簡稱RVO。您還將閱讀有關Named RVO (或NRVO)的資訊,它是相似的,但不遵循相同的規則。它有點復雜,超出了這個答案的范圍。
在 C 17 之前,average(A(1, 2, 3))實際上可能意味著A創建了一個臨時實體,并且函式中的移動或復制構造A函式必須從該臨時移動(或對于不可移動,復制)資源 - 這是通常很便宜,但不一定要便宜——而且它可能會帶來副作用。
有些型別既不能復制也不能移動。在這種情況下,呼叫在 C 17 之前無效。在 C 17 中,deleted移動和復制建構式在這種情況下無關緊要,因為沒有要移動或復制的實體 - 因此呼叫無疑是有效的。
當使用大括號括起來的初始值設定項串列時,正如您在本例中所做的那樣,甚至 C 11 也不允許創建(和移動)A. 這些值直接傳遞給A(float x, float y, float z).
除此之外,我無法在您的示例中發現差異。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/419324.html
標籤:
上一篇:C 標準是否保證std::vector的底層指標初始化為nullptr
下一篇:函式下呼叫函式時找不到識別符號
