通过参考传递复杂的真实和图像



问题: c 11已对复数进行了一些更改,以便无法再使用real()imag(),例如成员变量。我有一些我正在转换的代码,该代码将real()imag()通过参考将其传递给sincosf()。看起来有点像这样:

sincosf(/*...*/, &cplx.real(), &cplx.imag());

现在给出一个error: lvalue required as unary '&' operand

在C 11之前未收到哪些错误。

我的问题:是否有简单的内联修复?还是我必须创建临时变量才能获取结果,然后通过setters将这些变量传递给复杂数字?

谢谢

作为T.C.在评论中提到,标准允许您 reinterpret_cast std::complex满足您内心的内容。

来自N3337,§26.4/4 [complex.numbers]

如果 z cv std::complex<T>类型的lvalue表达式:
&mdash;reinterpret_cast<cv T(&)[2]>(z)表达式应构成良好,
&mdash;reinterpret_cast<cv T(&)[2]>(z)[0]应指定z的实际部分,
&mdash;reinterpret_cast<cv T(&)[2]>(z)[1]应指定z的虚构部分。
此外,如果a是类型 cv std::complex<T>*的表达式,并且表达式a[i]对于整数表达式i已很好地定义,则:
&mdash;reinterpret_cast<cv T*>(a)[2*i]应指定a[i]的实际部分,
&mdash;reinterpret_cast<cv T*>(a)[2*i + 1]应指定a[i]的虚构部分。

因此,在代码中进行以下替换

sincosf(/*...*/, 
        &reinterpret_cast<T*>(&cplx)[0], 
        &reinterpret_cast<T*>(&cplx)[1]);

只是做

cplx = std::polar(1.0f, /*...*/);

不要以为良好的优化编译器(例如gcc -O3)。

请参阅gcc -O3的结果组件:https://goo.gl/ucpaa9

使用此代码:

#include<complex>
std::complex<float> scf1(float x) {
  float r = 0., i = 0.;
  sincosf(x, &r, &i);
  return std::complex<float>(r, i);
}
void scf2(std::complex<float>& cmp, float x) {
  float r = 0., i = 0.;
  sincosf(x, &r, &i);
  cmp.real(r);
  cmp.imag(i);
}
void scf3(std::complex<float>& cmp, float x) {
  float r = 0., i = 0.;
  sincosf(x, &cmp.real(), &cmp.imag());
}

scf2等于您的语句,您可以在三种情况下看到非常相似的组件。

scf1(float):
    subq    $24, %rsp
    leaq    8(%rsp), %rsi
    leaq    12(%rsp), %rdi
    call    sincosf
    movss   12(%rsp), %xmm0
    movss   %xmm0, (%rsp)
    movss   8(%rsp), %xmm0
    movss   %xmm0, 4(%rsp)
    movq    (%rsp), %xmm0
    addq    $24, %rsp
    ret
scf2(std::complex<float>&, float):
    pushq   %rbx
    movq    %rdi, %rbx
    subq    $16, %rsp
    leaq    8(%rsp), %rsi
    leaq    12(%rsp), %rdi
    call    sincosf
    movss   12(%rsp), %xmm0
    movss   %xmm0, (%rbx)
    movss   8(%rsp), %xmm0
    movss   %xmm0, 4(%rbx)
    addq    $16, %rsp
    popq    %rbx
    ret
scf3(std::complex<float>&, float):
    pushq   %rbx
    movq    %rdi, %rbx
    subq    $16, %rsp
    leaq    8(%rsp), %rsi
    leaq    12(%rsp), %rdi
    call    sincosf
    movss   12(%rsp), %xmm0
    movss   %xmm0, (%rbx)
    movss   8(%rsp), %xmm0
    movss   %xmm0, 4(%rbx)
    addq    $16, %rsp
    popq    %rbx
    ret

最新更新