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 那样直接汇编输出的副作用。
我希望能够定义一个像这样工作的自定义运算符:
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 那样直接汇编输出的副作用。