GCC 忽略默认成员值初始化
default member value initialization is ignored in GCC
我在下面的代码中发现了一个意想不到的行为(据我所知),它不遵守默认成员初始化值。我有一个承包商用于单个参数赋值,它应该从赋值运算符构建 class 。我忘了使用正确的参数名称,结果遇到了这个问题(请参阅带有故意错误的单参数构造函数行:
为什么我得到的是垃圾值而不是成员初始化值?
我自己的假设是因为模板化 class,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;
}
示例输出:
Complex: Default constructor cA=0, 0
Complex: Constructing from assignement! cB=6.91942e-310, 0
Complex: Constructing from assignement! cC=4199661, 0
代码在CompilerExplorer.
Complex(T real) : re{re} { // should be re{real}, but why re{re} is not 0?
如果您在构造函数中显式地为成员提供初始值设定项,则此初始值设定项替换默认成员初始值设定项。默认成员初始值设定项在这种情况下根本不使用。
需要说明的是:默认成员初始值设定项不会在调用构造函数之前初始化成员。它们只是“填充”构造函数的成员初始化器列表中未提及的成员的初始化器。
在你的例子中,re{re}
访问了一个超出其生命周期的对象 (re
),导致了未定义的行为。
此外,作为旁注:Complex<double> cB = 1.0;
和 Complex<int> cC = 1;
不是 作业 。两者都是带有初始化的声明。 =
不是赋值表达式的一部分,不会像赋值那样调用 operator=
。它们都是 copy-initialization,与 Complex<double> cB(1.0);
相反,后者是 direct-initialization.
这些初始化所使用的构造函数 Complex(T real)
称为 转换构造函数 。
我在下面的代码中发现了一个意想不到的行为(据我所知),它不遵守默认成员初始化值。我有一个承包商用于单个参数赋值,它应该从赋值运算符构建 class 。我忘了使用正确的参数名称,结果遇到了这个问题(请参阅带有故意错误的单参数构造函数行:
为什么我得到的是垃圾值而不是成员初始化值?
我自己的假设是因为模板化 class,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;
}
示例输出:
Complex: Default constructor cA=0, 0 Complex: Constructing from assignement! cB=6.91942e-310, 0 Complex: Constructing from assignement! cC=4199661, 0
代码在CompilerExplorer.
Complex(T real) : re{re} { // should be re{real}, but why re{re} is not 0?
如果您在构造函数中显式地为成员提供初始值设定项,则此初始值设定项替换默认成员初始值设定项。默认成员初始值设定项在这种情况下根本不使用。
需要说明的是:默认成员初始值设定项不会在调用构造函数之前初始化成员。它们只是“填充”构造函数的成员初始化器列表中未提及的成员的初始化器。
在你的例子中,re{re}
访问了一个超出其生命周期的对象 (re
),导致了未定义的行为。
此外,作为旁注:Complex<double> cB = 1.0;
和 Complex<int> cC = 1;
不是 作业 。两者都是带有初始化的声明。 =
不是赋值表达式的一部分,不会像赋值那样调用 operator=
。它们都是 copy-initialization,与 Complex<double> cB(1.0);
相反,后者是 direct-initialization.
这些初始化所使用的构造函数 Complex(T real)
称为 转换构造函数 。