C++ 中的自定义运算符重载,没有开销

A custom operator overload in C++ without overhead

我希望能够定义一个像这样工作的自定义运算符:

struct Matrix {
    int inner[5];
    static Matrix tensor_op(Matrix const& a, Matrix const& b);
};

int main()
{
    Matrix a;
    Matrix b;
    Matrix c = a tensor c;
    return 1;
}

下面的代码工作完美,只是它没有优化掉中间对象:

template<char op> struct extendedop { }; 
template<typename T, char op>
struct intermediate {
    T const& a;
    intermediate(T const& a_) : a(a_) {}
}; 
template<typename T, char op>
intermediate<T, op> operator+(T const& a, extendedop<op> exop) {
    return intermediate<T, op>(a);
}
template<typename T>
T operator+(intermediate<T, '*'> const& a, T const& b) {
    return T::tensor_op(a.a, b);
}
#define tensor + extendedop<'*'>() +

正如您在 decompiled assembly code 中看到的,当使用 GCC 和 MSVC 编译时,只有 GCC 可以优化掉中间对象。

如何让 MSVC 优化掉不必要的代码?

经过MSVC优化。查看main()的生成代码(使用/GS-去除安全检查,只是为了更清楚):

$LN10:
  sub rsp, 120 ; 00000078H
  lea r8, QWORD PTR c$[rsp]
  lea rdx, QWORD PTR a$[rsp]
  lea rcx, QWORD PTR $T1[rsp]
  call static Matrix Matrix::tensor_op(Matrix const &,Matrix const &) ; Matrix::tensor_op
  mov eax, 1
  add rsp, 120 ; 00000078H
  ret 0
main ENDP

这与 GCC 的指令数相同。省略了中间对象的构造。

Compiler Explorer 上生成的额外程序集只是 MSVC 为运算符添加代码,以防它们被独立使用,并且在不使用时不会被清除。这可能只是它没有像 GCC/Clang 那样直接汇编输出的副作用。