是基元铸造,在内存中创建一个新对象

Is primitive casting, creates a new object in memory?

本文关键字:一个 对象 新对象 创建 内存      更新时间:2023-10-16

我的问题很简单,如果我在C++中有以下代码:

int main(int argc, const char * argv[])
{
    int i1 = 5;
    int i2 = 2;
    float f = i1/(float)i2;
    std::cout << f << "n";
    return 0;
}

(float)i2是否将在内存中创建一个新对象,该对象下一步将设计i1并分配给f,或者铸造运算符正在以某种方式动态转换(float)i2并在没有额外内存用于铸造的情况下进行设计?

此外,铸造需要不同大小的变量的情况是怎么回事?(例如从浮动到双)

(float)i2将在内存中创建一个新对象吗

强制转换将创建一个临时对象,该对象将有自己的存储空间。这不一定在记忆中;像这样的小算术值很可能会被创建并在寄存器中使用。

此外,铸造需要不同大小的变量的情况是怎么回事?

既然创建了一个新对象,那么它们是否具有不同的大小和表示方式并不重要。

它取决于编译器实现和机器体系结构。编译器可以为临时变量使用CPU寄存器,如果需要,也可以使用堆栈内存。研究编译器的汇编级输出可以告诉你它在特定情况下会做什么。

转换的值可以存储在内存或寄存器中。这取决于您的硬件、编译器和编译选项。考虑一下在cygwin 64位gcc:上使用g++ -O0 -c -g cast_code.cpp编译代码段的结果

  [...]
  14:   c7 45 fc 05 00 00 00    movl   $0x5,-0x4(%rbp)
    int i2 = 2;
  1b:   c7 45 f8 02 00 00 00    movl   $0x2,-0x8(%rbp)
    float f = i1/(float)i2;
  22:   f3 0f 2a 45 fc          cvtsi2ssl -0x4(%rbp),%xmm0
  27:   f3 0f 2a 4d f8          cvtsi2ssl -0x8(%rbp),%xmm1
  2c:   f3 0f 5e c1             divss  %xmm1,%xmm0
  30:   f3 0f 11 45 f4          movss  %xmm0,-0xc(%rbp)
  [...]

int被移到堆栈上,然后转换为浮点值,这些浮点值存储在mmx寄存器中。新对象?可辩论的;在内存中:而不是(取决于什么是内存;对我来说,内存应该是可寻址的)。

如果我们指示编译器正确存储变量(例如,为了避免更精确寄存器的精度问题),我们会得到以下结果:

g++ -O0 -c -g -ffloat-store cast_code.cpp导致

  // identical to above
  14:   c7 45 fc 05 00 00 00    movl   $0x5,-0x4(%rbp)
    int i2 = 2;
  1b:   c7 45 f8 02 00 00 00    movl   $0x2,-0x8(%rbp)
    float f = i1/(float)i2;
  // same conversion
  22:   f3 0f 2a 45 fc          cvtsi2ssl -0x4(%rbp),%xmm0
  // but then the result is stored on the stack.
  27:   f3 0f 11 45 f4          movss  %xmm0,-0xc(%rbp)
  // same for the second value (which undergoes an implicit conversion).
  2c:   f3 0f 2a 45 f8          cvtsi2ssl -0x8(%rbp),%xmm0
  31:   f3 0f 11 45 f0          movss  %xmm0,-0x10(%rbp)
  36:   f3 0f 10 45 f4          movss  -0xc(%rbp),%xmm0
  3b:   f3 0f 5e 45 f0          divss  -0x10(%rbp),%xmm0
  40:   f3 0f 11 45 ec          movss  %xmm0,-0x14(%rbp)

看到i1如何在27处从寄存器移动到存储器,然后在36处返回寄存器,以便在3b处执行除法,这有点痛苦。

不管怎样,希望能有所帮助。

相关文章: