簡體   English   中英

當存在可用的右值構造函數時,為什么從右值調用 class 引用構造函數重載?

[英]Why does the class reference constructor overload get called from an rvalue when there's an rvalue constructor available?

這段代碼

#include <iostream>

struct A
{
    A(int i) {std::cout << "int received\n";}
    A(A& a) {std::cout << "ref received\n";}
};

int main()
{
    int j = 5;
    A a = j;
}

意外引發以下編譯器錯誤:

error: invalid initialization of non-const reference of type 'A&' from an rvalue of type 'A'
note:   initializing argument 1 of 'A::A(A&)'
note:   after user-defined conversion: A::A(int)

當我刪除第二個構造函數重載A(A& a)時,一切都按預期工作。 我想編譯器錯誤地調用了第二個構造函數而不是第一個。

為什么會這樣?

如何讓 class 與參考構造函數和右值構造函數協調工作?

我使用 GNU GCC。

注意:我還注意到一些奇怪的事情:顯然,如果我替換行A a = j; A a(j); ,一切都按預期工作。 然而,這並不令人滿意,因為如果我嘗試從 function 參數初始化 object (例如:使用f(j)調用void f(A a) ,它仍然不起作用。

A a = j; 執行 復制初始化

直到 C++17,

如果T是 class 類型,且other的類型的 cv-unqualified 版本不是T或派生自T ,或者如果T是非類類型,但other的類型是 class 類型,用戶定義的轉換序列可以從other的類型轉換為T (或從T派生的類型,如果T是 class 類型並且轉換 function 可用)進行檢查,並通過重載決議選擇最佳的。 如果使用了轉換構造函數,則轉換結果是一個prvalue temporary (until C++17) prvalue expression (since C++17) ,然后用於直接初始化object。 The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

Class A有一個復制構造函數,將左值引用指向非 const,它不能綁定到從int臨時轉換的臨時變量。 即使是臨時A的構造也可能被優化,復制構造函數必須可用。

使復制構造函數對const進行左值引用(或添加移動構造函數)將解決該問題。

由於 C++17 由於強制復制省略,代碼可以正常工作。

對象直接構建到存儲中,否則它們將被復制/移動到。 復制/移動構造函數不需要存在或可訪問:

居住

另一方面, A a(j); 直接初始化a直接從j初始化,不涉及拷貝構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM