4

找出在我的 C++ 代码中创建临时对象的位置的最快方法是什么?

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

我已经尝试过godbolt.org和它太棒了。不幸的是,当涉及到临时工时,它经常将树木隐藏在装配工的木头后面。此外,激进的编译器优化选项使汇编器完全不可读。

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

4

2 回答 2

4

“编译器优化可以进一步消除临时性。”

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

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

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

于 2018-01-24T10:34:32.077 回答
2

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

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

临时对象的物化通常尽可能地延迟,以避免创建不必要的临时对象。[注意:临时对象被物化:

  • 当绑定对prvalue的引用时([dcl.init.ref]、[expr.type.conv]、[expr.dynamic.cast]、[expr.static.cast]、[expr.const.cast]、[expr 。投掷]),

  • 在对类纯右值([expr.ref]、[expr.mptr.oper])执行成员访问时,

  • 在对数组纯右值执行数组到指针的转换或下标时,

  • 从花括号初始化列表 ([dcl.init.list]) 初始化 std​::​initializer_list 类型的对象时,

  • 对于某些未计算的操作数([expr.typeid]、[expr.sizeof]),以及

  • 当纯右值显示为废弃值表达式时。

在这段来自 C++17 标准的段落中,prvalue一词有一个新定义[basic.lval]/1

prvalue 是一个表达式,它的求值初始化一个对象或一个位域,或者计算一个运算符的操作数的值,由它出现的上下文指定。

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

于 2018-01-24T10:52:44.803 回答