我在下面的代碼中提出了一個意想不到的行為(據我自己有限的知識),它不尊重默認成員初始化值。我有一個單一引數賦值的承包商,它假設從賦值運算子構建類。我忘記使用正確的引數名稱,最終遇到了這個問題(請參閱帶有故意錯誤的單引數建構式的行:
為什么我得到垃圾值而不是成員初始化值?
我自己的假設是因為模板化類,0與0.0不一樣......但嘗試過 并遇到了同樣的問題。
#include <iostream>
#include <concepts>
template <class T>
requires std::is_arithmetic_v<T>
class Complex
{
private:
T re = 0;
T im = 0;
public:
Complex() {
std::cout << "Complex: Default constructor" << std::endl;
};
Complex(T real) : re{re} { // should be re{real}, but why re{re} is not 0?
std::cout << "Complex: Constructing from assignement!" << std::endl;
};
void setReal(T t) {
re = t;
}
void setImag(const T& t) {
im = t;
}
T real() const {
return re;
}
T imag() const {
return im;
}
Complex<T>& operator =(const Complex<T> other) {
re = other.re;
im = other.im;
return *this;
}
bool operator<(const Complex<T>& other) {
return (re < other.re && im < other.im);
}
};
int main() {
Complex<double> cA;
std::cout<< "cA=" << cA.real() << ", " << cA.imag() << "\n";
Complex<double> cB = 1.0; // Should print "1.0, 0" but prints garbage
std::cout<< "cB=" << cB.real() << ", " << cB.imag() << "\n";
Complex<int> cC = 1;
std::cout<< "cC=" << cC.real() << ", " << cC.imag() << "\n";
return 0;
}
示例輸出:
復雜:默認建構式 cA=0, 0 復雜:從賦值構造!cB=6.91942e-310, 0 Complex:從賦值構造!cC=4199661, 0
CompilerExplorer上的代碼。
uj5u.com熱心網友回復:
Complex(T real) : re{re} { // should be re{real}, but why re{re} is not 0?
如果在建構式中顯式地為成員提供了初始化器,則該初始化器將替換默認成員初始化器。默認成員初始值設定項在這種情況下根本不使用。
需要明確的是:默認成員初始值設定項不會在建構式呼叫之前初始化成員。他們只是為建構式的成員初始值設定項串列中未提及的成員“填充”了初始值設定項。
在您的情況下,re{re}訪問生命周期之外的物件 ( re),導致未定義的行為。
另外,作為旁注:Complex<double> cB = 1.0;andComplex<int> cC = 1;不是assignments。兩者都是帶有初始化的宣告。該=不是賦值運算式的一部分,并不會呼叫operator=為將分配。它們都是copy-initialization,與之相反的Complex<double> cB(1.0);是direct-initialization。
Complex(T real)這些初始化中的任何一個使用的構造函式稱為轉換建構式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/397255.html
上一篇:模板物件的賦值和添加多載
