显示在 C++ 中创建临时文件的位置

Show where temporaries are created in C++

找出在我的 C++ 代码中创建临时文件的最快方法是什么?

答案并不总是很容易从标准中推导出来,编译器优化可以进一步消除临时变量。

我已经尝试过 godbolt.org 并且非常棒。不幸的是,当涉及到临时文件时,它经常将树隐藏在汇编程序的木头后面。此外,激进的编译器优化选项使汇编程序完全不可读。

还有其他方法可以做到这一点吗?

"compiler optimizations can further eliminate temporaries."

看来你对C++的语义有点误解。 C++ 标准讨论临时对象来定义程序的形式语义。这是描述大量可能执行的紧凑方式。

实际的编译器根本不需要这样。通常,他们不会。真正的编译器知道寄存器,真正的编译器不会假装 POD 具有(普通的)构造函数和析构函数。这在优化之前就已经发生了。我不知道有哪个编译器会在调试模式下生成普通的 ctors。

现在标准描述的一些语义只能通过相当接近的近似来实现。当析构函数有明显的副作用时(想想 std::cout),这些类型的临时变量不能完全消除。但是真正的编译器可能会在不分配任何存储空间的情况下实现可见的副作用。暂时存在或暂时不存在的概念是二元论,实际上存在中间形式。

由于 "as-if" 规则,尝试查看编译过程以查看创建临时文件的位置可能不可靠。

但是在阅读代码(和编码)的同时牢记标准的以下段落可能有助于找到临时文件的创建位置,[class.temporary]/2

The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary objects. [ Note: Temporary objects are materialized:

  • when binding a reference to a prvalue ([dcl.init.ref], [expr.type.conv], [expr.dynamic.cast], [expr.static.cast], [expr.const.cast], [expr.cast]),

  • when performing member access on a class prvalue ([expr.ref], [expr.mptr.oper]),

  • when performing an array-to-pointer conversion or subscripting on an array prvalue,

  • when initializing an object of type std​::​initializer_­list from a braced-init-list ([dcl.init.list]),

  • for certain unevaluated operands ([expr.typeid], [expr.sizeof]), and

  • when a prvalue appears as a discarded-value expression.

在来自 C++17 标准的这段中,术语 prvalue 有了新的定义 [basic.lval]/1:

A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.

并且在上一个标准(C++20 之前)中,段落 [basic.lval] 已移至 Expressions [expr],所以我们知道因为值类别正在演变为表达类别。