boost :: scoped_ptr是否违反了逻辑constness的准则

时间:2011-07-16 16:00:29

标签: c++ const smart-pointers boost-smart-ptr

在boost :: scoped_ptr operator*operator->中声明了const个函数,尽管它们返回T&T*,它们可能允许客户端更改底层数据。这违反了逻辑常量的概念(Myers,Effective C ++)

const函数不应该有签名吗?

const T& operator*() const;
const T* operator->() const;

3 个答案:

答案 0 :(得分:6)

这里的基本问题是scoped_ptr对象的行为更像是指针而不是类对象(即使scoped_ptr实例实际上是类对象)。

Boost提供的智能指针类旨在尽可能保留原始指针语义,同时提供附加功能,如引用计数或(在本例中)RAII语义。

为此,编写operator*()的{​​{1}}和operator->()成员,使其“constness behavior”基本上与原始指针的匹配。

用“愚蠢”的指针来考虑这种情况:

scoped_ptr

// Can change either Foo or ptr. Foo* ptr; // Can't change Foo via ptr, although ptr can be changed. const Foo* ptr; // Can't change ptr, although Foo can be changed via ptr. Foo* const ptr; // Can't change Foo or ptr. const Foo* const ptr; 类似物看起来像这样:

scoped_ptr

编写运算符的方式使得上面的代码片段成为可能,即使// Can change either Foo or ptr. scoped_ptr<Foo> ptr; // Can't change Foo via ptr, although ptr can be changed. scoped_ptr<const Foo> ptr; // Can't change ptr, although Foo can be changed via ptr. const scoped_ptr<Foo> ptr; // Can't change Foo or ptr. const scoped_ptr<const Foo> ptr; 实际上不是原始指针。

在所有情况下,代码都需要能够取消引用scoped_ptr。通过创建运算符ptr,可以在const和非const const上调用dereference / member-access运算符。

请注意,如果用户声明scoped_ptr,则会有以下成员:

scoped_ptr<Foo>

Foo& operator*() const; Foo* operator->() const; 会有这些成员:

scoped_ptr<const Foo>

因此指针的const-correctness行为实际上是以这种方式保留的。

但不多了,否则他们不会是聪明的指针!

答案 1 :(得分:1)

  

在boost :: scoped_ptr operator *和operator-&gt;中声明为const函数,尽管它们返回T&amp;和T *可能允许客户更改基础数据。

“基础数据”不是智能指针值的一部分。如果两个(智能)指针指向同一个对象,它们是相等的:a == b iff &*a == &*b

  

这违反了逻辑 constness(Myers,Effective C ++)的想法

不,它没有:

智能指针的逻辑值仅取决于它指向的内容。

取消引用智能指针不会改变指向的内容。

因此,取消引用智能指针不会更改其逻辑值(或者如果您愿意,则更改其状态)。

QED

答案 2 :(得分:0)

scoped_ptr<T>就像T*。它不像T* const

scoped_ptr<T const>就像是T const*(你可以写成const T*)而只有你期望operator*和{{ 1}}返回operator->件事。