临时对象如何存储和处理?

时间:2018-04-20 07:35:43

标签: c++ rvalue

考虑这个例子:

int a = 5;
int b = 10;
int c = a + b; //where is the value of (a+b) stored?
a = a + b; //how about now?

我的理解是临时对象的处理方式类似于新的局部变量,即它们位于堆栈顶部。但是在我的例子的第3行中,将(a + b)直接提升到c?还是复制?它会在第4行复制到?

的位置

编辑:修复语法错误。 为什么我关心?因为我正在寻找一般答案,例如当我不使用int而是使用大对象或者可能是堆对象的包装器时。

3 个答案:

答案 0 :(得分:4)

允许C ++编译器按照" as-if"编译代码。规则:也就是说,您编写的源代码描述了程序的意图,而不是编译代码。

因此,编译器可能会将您的代码重构为

int b = 10;
int c = 15;
int a = 15;

或者,根据变量的任何后续使用情况,它可能会忽略它们。最后,请注意堆栈是一种实现概念,而不是语言概念。除了几个C ++标准库函数之外,C ++标准本身根本没有提到堆栈。

答案 1 :(得分:4)

为什么要关心?为什么要存放在任何地方?代码

a = a + b; 

将使编译器创建与您期望的行为相似的代码,在您首先需要知道的所有内容中。可能是中间值只存储在某个cpu寄存器中,可能是它没有存储在任何地方,可能是编译器会执行与此相同的操作:

int temp = a + b;
a = temp;

另一方面,如果您确实关心编译器对代码的作用,则需要查看其输出。编译器是相当复杂的野兽,做出一般假设通常是错误的。这是检查编译器输出的一个很棒的工具:https://godbolt.org/

答案 2 :(得分:0)

对于内在类型,无所谓;可观察的行为很容易确定,并且所有类型的优化都会发生。 但是对于UDT来说,长话故事。如果临时值被值抓住:

  1. 如果对象是可复制构造类型并且发现重定位是可以避免的,则会发生复制省略。
  2. 如果是可移动类型且选项1不适用,则移动构造发生。在这种情况下,临时保留在一些轻量级零状态,将以低开销进行破坏。
  3. 复制构造发生在对象具有可复制构造的无可移动类型且重定位不可避免的情况下。在这种情况下,临时将以其原始值被破坏,并且可能是很高的开销。
  4. 如果通过引用抓取UDT临时值,它的生命周期将扩展到引用的范围,它将被视为普通左值。不会发生任何复制/移动。当参考死亡时会发生破坏。