首页 > 解决方案 > 使用方法是否总是意味着通过“this”指针间接访问成员字段?

问题描述

我想知道这种类型的事情是否属于编译器的优化范围。从我从这次谈话中收集到的内容来看,甚至std::unique_ptr不是真正的“零成本”,部分原因是指针的隐式间接this在将实际底层指针传递给唯一指针的成员函数方面发挥了作用。

在将成员字段传递给类的方法时是否总是存在引用,或者编译器是否可以看到,说这个方法不使用某些字段并且不修改其余字段,所以它只会按值传递它们?

标签: c++

解决方案


谈话内容似乎有些误解。有一个关于为什么unique_ptr不是“零成本”的讨论。然而,该讨论集中在一个具体案例,即所有权转让。一方面,既然存在有成本的情况,那确实unique_ptr不是零成本。另一方面,这个结论具有误导性,因为它听起来就像说它是零成本一样包罗万象。更准确的描述将结合这两种观点:unique_ptr 可以零成本替代原始指针,但并非总是如此。

Aunique_ptr可以是零成本。谈话结束时问答环节的第一个问题解决了这个问题(从 36:36 开始)。的大多数成员函数smart_ptr都很简单,可以被任何理解模板语法的 C++ 编译器内联。没有与this指针和成员函数相关的开销。如果您从不转让所有权,请继续将其unique_ptr视为零成本。

所有权转移时会产生额外的成本。该演讲特别关注将 aunique_ptr作为参数传递给函数。这明确地赋予了被调用函数对指针指向的任何内容的所有权。它还需要额外的运行时成本(如果原始指针版本缺乏异常安全性,则需要额外的两个成本)。

额外的成本不是 C++ 语言固有的,而是来自常用的 ABI(应用程序二进制接口)。ABI 在低级别(想想汇编)定义参数如何传递给函数。T*根据这个约定,和之间有一个重要的区别unique_ptr<T>– 前者是原始类型,而后者是类的实例。如果我正确理解了这部分谈话,ABI 要求将原始类型直接放在调用堆栈中(可能简单地存储在寄存器中),而类实例必须存在于主内存中,并且直接放置指向实例的指针在堆栈中/可能在寄存器中。是的,即使对象是按值传递的。为什么?因为这就是公约所要求的。(有更好的理由,但它们与当前主题无关。)为了让动态库之类的东西起作用,需要有一个约定,而这个 ABI 就是我们所拥有的。

结果是原语得到了优惠待遇,使它们更快。当您将函数的参数从指针切换到类实例时,会产生运行时成本(大小未知——它可能微不足道)。这是unique_ptr在所有情况下都无法实现零成本的成本。在许多常见情况下是零成本,但在函数接受unique_ptr参数时则不然。


推荐阅读