为什么unique_ptr的operator->没有进行const重载?

13

std::unique_ptr::operator-> 的签名如下:

The signature of std::unique_ptr::operator-> is as follows:
pointer operator->() const noexcept;

因此,operator->是const但返回一个可变指针。这允许像下面这样的代码:

void myConstMemberFunction() const
{
    myUniquePtrMember->nonConstFunction();
}
为什么标准允许这样做,以及防止像上面展示的用法的最佳方法是什么?

我认为这是因为运算符“.”无法被重载。 - erip
3
在C++中,const是浅层的。一个int* const也可以允许你修改所指向的对象。 - Bo Persson
5
如果指针不是智能指针,那么相同的代码将被允许。const只适用于指针本身,而不是指向的内容。 - juanchopanza
2
如果您想要传播它,我们有std::experimental::propagate_const - T.C.
2
关于 const 的常见误解。 - Lightness Races in Orbit
@T.C. 感谢您提供有关 propagate_const 的提示。这似乎是确保智能指针成员的常量正确性的好方法。 - khuttun
2个回答

19

就像一个普通指针一样思考:

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 *是对非constintconst指针,这是错误的。


7

这是指针的传统语义。一个const指针是一个不能被改变的指针,但它所指向的对象可以被改变。

struct bar {
  void do_bar() {}
};

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

为了避免改变指针所指向的对象,您需要使用指向常量的const指针的unique_ptr等效物,或者...
const std::unique_ptr<const bar> b;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接