3

我对 C++ 很陌生。我一直认为shared_ptr是保持单独的指针指向单独的引用计数器变量。但是今天突然意识到其实我不知道它是怎么布局的,而且引用值在C++中不需要有分隔指针。

如果布局是由标准定义的,那么正确的预期布局是std::shared_ptr什么?

4

1 回答 1

4

C++ 标准没有为任何非标准布局类定义它应该如何在内存中布局,例如 [class.mem]/13

分配具有相同访问控制(第 11 条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。未指定具有不同访问控制的非静态数据成员的分配顺序(第 11 条)。实现对齐要求可能会导致两个相邻的成员不会被立即分配;管理虚拟功能 (10.3) 和虚拟基类 (10.1) 的空间要求也是如此。

标准布局类型有一些例外/简化,但类的内存布局没有通用规范。

这也适用于标准库中的类。除此之外,标准只定义了这些类的要求,其中一些是成员函数签名意义上的“接口”。在 [objects.within.classes] 中非常明确:

1) 第 18 到 30 条和附录 D [即标准库] 没有指定类的表示,并且有意省略了类成员的规范 (9.2)。实现可以定义静态或非静态类成员,或两者,根据需要实现第 18 到 30 条和附录 D 中指定的成员函数的语义。

2) 某些类的对象有时需要其类的外部规范来存储数据,显然是在成员对象中。为了说明起见,一些子条款为满足类的外部规范的类的私有成员对象提供了代表性声明和语义要求。此类成员对象的声明和相关成员类型的定义后跟仅以说明结尾的注释,如:

streambuf* sb; // exposition only

也就是说,对所需功能的一些说明std::shared_ptr

  • 您需要将拥有对象的引用计数存储在包含此所有权信息的动态分配的对象中(dyn.alloc。因为不清楚哪个shared_ptr是最后一个活着的,最后一个必须解除分配它)
  • 您还需要存储此所有权信息对象的引用计数以供使用weak_ptr,asweak_ptr::expiredweak_ptr::lock可能不会失败(例如,通过访问冲突)

迂腐的旁白:标准不要求shared_ptr 泄漏内存,但 PC 类型架构的典型实现可能会使用动态内存分配。

std::make_sharedbtw 被认为比使用 ctor 更快,std::shared_ptr因为它可以在一次分配中为拥有的对象和所有权信息对象分配内存(标准说“实现应该执行不超过一次的内存分配。”,尽管那是只有一个备注)。

于 2013-07-13T08:26:53.857 回答