std::complex 初始化问题

std::complex initilalisation issue

考虑以下代码

#include <complex>
#include <iostream>

int main(int argc, char **argv)
{
    std::complex<double> a = 1+1i;
    std::cout<<"a ="<<a<<"\n";
    return 0;
}

当我使用 Apple LLVM 版本 8.0.0 (clang-800.0.42.1) 进行编译时,我得到的输出是

a =(1,0)

谁能解释一下为什么虚部初始化为零?

1 + 1i 正在使用 (GCC) 扩展创建类型 similar/equivalent 到 C99 的 _Complex int 类型。该类型可转换为真实类型,如 intdoublestd::complex_Complex 不兼容,它没有任何构造函数可以从 _Complex (*) 创建 std::complex。但是 std::complex<T> 确实有一个采用 T 的构造函数。这会触发上述转换 _Complex -> T -> std::complex<T>.

因此 OP 中的代码等同于:

#include <complex>
#include <iostream>

int main()
{
    double d = 1+1i;
    std::complex<double> a = d;
    std::cout<<"a ="<<a<<"\n";
    return 0;
}

1 + 1i 的虚部在转换为 double 时被舍去。


为防止出现此类意外,请尝试使用警告和 -pedantic 进行编译。这个例子似乎是 clang 实际上使用 -pedantic 标志添加额外警告的少数几个地方之一(对于 gcc,-pedantic 在许多情况下更改警告输出):

prog.cc:6:19: warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]
    double d = 1+1i;

(*) IIRC,std::complex 是在 C++98 中引入的,而 _Complex 是在 C99 中引入的。