为什么在存在隐式转换时赋值速度变慢?

Why is assignment slower when there's an implicit conversion?

如果有类似的问题请指导我,我安静地搜索了一段时间但没有找到任何东西。

背景:

我只是在玩耍,发现了一些我无法完全解释的行为...... 对于原始类型,看起来当存在隐式转换时,与显式赋值相比,赋值运算符 = 需要更长的时间。

int iTest = 0;
long lMax = std::numeric_limits<long>::max();
for (int i=0; i< 100000; ++i)
{
    // I had 3 such loops, each running 1 of the below lines.
    iTest = lMax;
    iTest = (int)lMax;
    iTest = static_cast<int>(lMax);
}

结果是 c 风格转换和 c++ 风格 static_cast 平均执行相同(每次不同,但没有明显差异)。 AND 它们都优于隐式赋值。

Result:
iTest=-1, lMax=9223372036854775807
(iTest = lMax) used 276 microseconds

iTest=-1, lMax=9223372036854775807
(iTest = (int)lMax) used 191 microseconds

iTest=-1, lMax=9223372036854775807
(iTest = static_cast<int>(lMax)) used 187 microseconds

问题:

为什么隐式转换导致延迟较大?我可以猜到它必须在int溢出的赋值中检测到,所以调整为-1。但是作业中到底发生了什么?

谢谢!

如果你想知道幕后发生的事情的原因,最好的地方是……等等……幕后:-)

这意味着检查编译器生成的汇编语言。

最好将 C++ 环境视为 运行 C++ 代码的抽象机。该标准(大部分)规定了 行为 而不是实施细节。一旦离开 standard 的范围并开始思考下面发生的事情,C++ 源代码就不再有什么帮助了——您需要检查 actual code that the computer is 运行,编译器输出的东西(通常是机器码)。

可能是编译器放弃了循环,因为它每次都计算相同的东西,所以只需要执行一次。如果它可以确定您不使用结果,它可能会完全丢弃代码。

很久以前,VAX Fortran 编译器(我确实说过 很多 个月)在给定的基准测试中比竞争对手好几个数量级。

那是 确切 的原因。它确定没有使用循环的结果,因此优化了整个循环。


您可能需要注意的另一件事是测量工具本身。当您谈论 1/10,000th 秒的持续时间时,您的结果可能是被一点噪音淹没

有一些方法可以减轻这些影响,例如确保您测量的对象是实质性的(例如超过 10 秒),或者使用统计方法消除任何噪音。

但最重要的是,它可能是导致您看到的结果的测量方法。

#include <limits>

int iTest = 0;
long lMax = std::numeric_limits<long>::max();

void foo1()
{
  iTest = lMax;
}

void foo2()
{
  iTest = (int)lMax;
}

void foo3()
{
  iTest = static_cast<int>(lMax);
}

使用 -O3 使用 GCC 5 编译得到:

__Z4foo1v:
    movq    _lMax(%rip), %rax
    movl    %eax, _iTest(%rip)
    ret

__Z4foo2v:
    movq    _lMax(%rip), %rax
    movl    %eax, _iTest(%rip)
    ret

__Z4foo3v:
    movq    _lMax(%rip), %rax
    movl    %eax, _iTest(%rip)
    ret

它们完全一样。

由于您没有提供完整的示例,我只能猜测差异是由于您没有向我们展示的内容造成的。