在 boost::scoped_ptr 中,operator*
和 operator->
被声明为 const
函数,尽管它们返回 T&
和 T*
可能允许客户端更改基础数据。这违反了逻辑常量的思想(Myers,Effective C++)
const 函数不应该有签名吗?
const T& operator*() const;
const T* operator->() const;
最佳答案
这里的根本问题是 scoped_ptr
对象的行为更像指针而不是类对象(即使 scoped_ptr
实例实际上是类对象)。
Boost 提供的智能指针类旨在尽可能保留原始指针语义†,同时提供附加功能,如引用计数或(在本例中)RAII 语义。
为此,operator*()
和 operator->()
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
scoped_ptr
请注意,如果用户声明 scoped_ptr<Foo>
,它将有这些成员:
Foo& operator*() const;
Foo* operator->() const;
同时 scoped_ptr<const Foo>
会有这些成员:
const Foo& operator*() const;
const Foo* operator->() const;
所以指针的 const-correctness 行为实际上是以这种方式保留的。
†但不能再多了,否则它们就不是智能指针了!
关于c++ - boost::scoped_ptr 是否违反逻辑常量准则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6718538/