在 boost::scoped_ptroperator*
和operator->
被声明的const
函数中,尽管它们返回T&
并且T*
可能允许客户端更改底层数据。这违反了逻辑常量的思想(Myers,Effective C++)
const 函数不应该有签名吗?
const T& operator*() const;
const T* operator->() const;
在 boost::scoped_ptroperator*
和operator->
被声明的const
函数中,尽管它们返回T&
并且T*
可能允许客户端更改底层数据。这违反了逻辑常量的思想(Myers,Effective C++)
const 函数不应该有签名吗?
const T& operator*() const;
const T* operator->() const;
这里的基本问题是scoped_ptr
对象的行为更像是指针而不是类对象(即使scoped_ptr
实例实际上是类对象)。
Boost 提供的智能指针类旨在尽可能保留原始指针语义†</sup>,同时提供额外的功能,如引用计数或(在本例中)RAII 语义。
为此,编写了operator*()
and的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
. 通过制作操作符,可以在非 s和非sconst
上调用取消引用/成员访问操作符。const
const
scoped_ptr
请注意,如果用户声明 a scoped_ptr<Foo>
,它将具有以下成员:
Foo& operator*() const;
Foo* operator->() const;
虽然 ascoped_ptr<const Foo>
会有这些成员:
const Foo& operator*() const;
const Foo* operator->() const;
因此,指针的 const 正确性行为实际上是以这种方式保留的。
†</sup>但仅此而已,否则它们就不是智能指针!
在 boost::scoped_ptr 中, operator* 和 operator-> 被声明为 const 函数,尽管它们返回 T& 和 T* 可能允许客户端更改底层数据。
“基础数据”不是智能指针值的一部分。如果两个(智能)指针指向同一个对象,则它们相等:a == b
iff &*a == &*b
。
这违反了逻辑常量的思想(Myers,Effective C++)
不,不是的:
智能指针的逻辑值仅取决于它所指向的内容。
取消引用智能指针不会改变它指向的内容。
因此,取消引用智能指针不会更改其逻辑值(或您喜欢的状态)。
量子点
Ascoped_ptr<T>
就像一个T*
. 它不像一个T* const
.
Ascoped_ptr<T const>
就像 a T const*
(你可以写成const T*
),只有这样你才会期望operator*
并operator->
返回const
东西。