復制初始化是使用等號初始化左值的一種方法:
A a;
A b = a;
實際上b是呼叫復制建構式創建了物件。
有一種隱式型別別轉換特性,叫作轉換建構式,條件是類有一個需要傳入單個實參的建構式,允許從實參的型別轉換到型別別:
#include<iostream>
using namespace std;
class A{
public:
A()=default;
A(int a){cout<<"A(int) called"<<endl;}
A(const A&a);
~A(){cout<<"~A() called"<<endl;}
};
A::A(const A&a){
cout<<"A(const A&) called"<<endl;
}
int main(){
A a = 1;
}
g++編譯器和msvc編譯器(vs2017)似乎有不同的處理方法。
首先用g++編譯,用引數-fno-elide-constructors取消回傳值優化,得到的輸入如下:
似乎程序是這樣的:第一步,呼叫A(int)構造一個臨時物件;第二部呼叫A(const A&)復制建構式復制這個臨時物件。
給人的感覺是這樣的:
A a = A(1);
但是又不完全是,將復制建構式設為explicit:
#include<iostream>
using namespace std;
class A{
public:
A()=default;
A(int a){cout<<"A(int) called"<<endl;}
explicit A(const A&a);
~A(){cout<<"~A() called"<<endl;}
};
A::A(const A&a){
cout<<"A(const A&) called"<<endl;
}
int main(){
//A a = A(1); //錯誤:沒有合適的復制建構式
A b = 1; //ok
}
似乎
A b = 1;應該直接表現為
A b(A(1));
VS2017情況就不一樣了,似乎復制建構式根本不參與物件的構造,我把它設為explicit或者=delete,轉換構造依然可以執行。
到底哪一種符合標準呢?
uj5u.com熱心網友回復:
https://en.cppreference.com/w/cpp/language/copy_initializationIf T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary (until C++17)prvalue expression (since C++17) if a converting constructor was used, is then used to direct-initialize the 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)
你的g++可能在C++17范圍內,VS2017可能在C++17之后了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/25927.html
標籤:C++ 語言
上一篇:求教工程檔案的編譯問題
