为什么 unique_ptr operator-> 没有常量重载?

Why is unique_ptr operator-> not const-overloaded?

std::unique_ptr::operator-> 有签名

pointer operator->() const noexcept;

所以 operator-> 是 const 但 returns 是可变指针。这允许像这样的代码:

void myConstMemberFunction() const
{
    myUniquePtrMember->nonConstFunction();
}

为什么标准允许这样做,防止上述使用的最佳方法是什么?

把它想象成一个普通的指针:

int * const i;

是指向非 const intconst 指针。您可以更改 int,但不能更改指针。

int const * i;

是指向 const int 的非 const 指针。您可以更改指针但不能更改 int.


现在,对于 unique_ptr,问题是 const 是在 <> 的内部还是外部。所以:

std::unique_ptr<int> const u;

就像第一个。您可以更改 int,但不能更改指针。

你想要的是:

std::unique_ptr<int const> u;

您可以更改指针,但不能更改int。或者甚至:

std::unique_ptr<int const> const u;

此处不能更改指针 int


注意到我总是把 const 放在右边了吗?这有点不常见,但在处理指针时是必要的。 const 始终应用于紧邻其左侧的事物,例如 *(指针为 const)或 int。参见 http://kuhllib.com/2012/01/17/continental-const-placement/

写作 const int,可能会让您认为 int const * 是一个 const 指向非 const int 的指针,这是错误的。

这复制了传统指针的语义。 const 指针是不能改变的指针。但是,它指向的对象可以。

struct bar {
  void do_bar() {}
};

struct foo {
  void do_foo() const { b->do_bar(); } // OK
  bar* const b;
};

为避免指针对象发生变异,您需要 unique_ptr 等价于指向 const 的 const 指针,或者

const std::unique_ptr<const bar> b;