为什么复制const shared_ptr而不是违反const?

Tho*_*mas 7 c++ const shared-ptr

即使我的代码编译得很好,这也是困扰我的东西,我无法在stackoverflow上找到答案.以下泛型构造函数是将shared_ptr传递给构造函数中的类实例的一种方法.

MyClass {
  MyClass(const std::shared_ptr<const T>& pt);
  std::shared_ptr<const T> pt_;  //EDITED: Removed & typo
};

MyClass::MyClass(const std::shared_ptr<const T>& pt)
  : pt_(pt)
{ }
Run Code Online (Sandbox Code Playgroud)

编译好了.我的问题如下:在我的理解中,声明一个像这样的参数const:

void myfunc(const T& t)
Run Code Online (Sandbox Code Playgroud)

承诺不改变.但是,通过将shared_ptr pt复制到pt_,我是否有效地增加了shared_ptr pt的使用次数,从而违反了假定的常量?

这可能是对我这边的shared_ptrs的根本误解?

(对于任何阅读本文的人来说,请注意可能是一个更好的实现)

Mic*_*urr 6

std::shared_prt<>必须拥有的成员之一是旧式复制构造函数:

shared_ptr(const shared_ptr& r) noexcept;
Run Code Online (Sandbox Code Playgroud)

标准说(C++ 11 20.7.2.2.1/18"shared_ptr构造函数")"如果r为空,则构造一个空的shared_ptr对象;否则,构造一个与r共享所有权的shared_ptr对象".

该标准没有提到如何通过const引用来完成"与r共享所有权" .一些选项可能是:

  • 实现共享所有权语义的私有成员可能会被标记 mutable
  • 实现共享所有权的数据结构可能实际上并不存在于shared_ptr对象中 - 例如,它们可能是可能通过指针获取的单独对象集.


Ric*_*ges 5

共享指针的概念布局如下:

shared_ptr 包含一个指向对象的指针和一个指向控制块的指针。控制指针生命周期的是控制块,而不是shared_ptr对象本身,它只不过是一个包装器和一些代码来通知控制块引用的数量已经增加或减少。它是存储引用计数、删除器和指向被指点者原始接口的指针的控制块(因此,即使存在指针转换,删除器也可以针对正确的接口进行删除)。

* shared_ptr object *
| pointer to object | ---------------> object
| pointer to control block |----+   +> (possibly different interface
                                |   |   but still same object)
                                |   |
* control block *    <----------+   |
| reference count   |               |
| deleter           |               |
| pointer to object | --------------+
Run Code Online (Sandbox Code Playgroud)

由于 shared_ptr 的内存看起来像这样:

template<class T>
struct shared_ptr {
    T* ptr;
    control_block* pctrl;
};
Run Code Online (Sandbox Code Playgroud)

很明显,即使 shared_ptr 是 const,获取副本也不需要对 shared_ptr 的内部状态进行任何更改。突变发生在由 shared_ptr指向的控制块中。

因此合同没有被破坏。就像你宣布

T* const p;
Run Code Online (Sandbox Code Playgroud)

修改p本身是不可能的,但修改(*p)是完全合理的。