为什么std :: unique_ptr没有const get方法?

时间:2017-05-18 16:17:55

标签: c++ c++11 const smart-pointers

我理解std::unique_ptr是这样的,可能不会改变以打破向后兼容性但是我想知道是否有人有充分理由说明规范的编写者没有超载{{ 1}}具有类似

的const变体的方法
get

遵循const T* get() const; unique_ptr的意图。

我最好的猜测是它试图镜像指针并像const而不是典型的类一样行事。作为一个后续问题,如果我想在我的类的const实例中以类似const的方式持有一个指针,我应该使用除T* const之外的其他东西来保存数据吗?

更新

在我的情况下,我想保护自己不要滥用课堂本身的指针。我正在编写一个const移动构造函数std::unique_ptr,并通过MyClass(const MyClass&& other)将数据从新实例复制到其他实例。我花了很长时间来追踪这个bug,因为我认为副本必须是正确的,因为const保护。我正在试图弄清楚我可以做些什么来保护自己免受提供const getter以及在复制时在类中使用它的影响。

4 个答案:

答案 0 :(得分:5)

没有必要通过其unique_ptr对对象进行只读访问。您只有在转移所有权时才会传递unique_ptr,以便在没有所有权转移的情况下访问该对象,请致电up.get()并将const T*传递给只能读取的功能(或者如果指针永远不会nullptr,评估*(up.get())并传递const T&)也是合理的。

作为奖励,这允许您将该函数与存储在堆栈中的对象一起使用,嵌入到另一个对象中,或者使用unique_ptr以外的智能指针进行管理。

这里对所有unique_ptr参数传递案例(in / out,const / non-const等)进行了很好的讨论:

答案 1 :(得分:4)

出于同样的原因,T*const取消引用时为T&,而不是T const&

指针的常量与指向的点不同。

get是const,它不会修改unique_ptr状态

它的常量不会影响内容的常量。

智能指针的想法是传播常数,但unique_ptr不是那种野兽。

std::experimental::propogate_const包裹一个类似指针的对象,让const穿过它。

它或类似的东西可以解决你的问题。

请注意,当我尝试使用这样的const传播时,我发现有一半的时间,我发现我错了。但这可能不是这种情况。

一般来说,以T*const方式处理const内容的正确方法是传递T const&(或可空的变体T const*)。< / p>

答案 2 :(得分:2)

智能指针假装是原始指针。 如果您的类成员是原始指针并在const方法中使用它,您无法更新指针,但您可以修改指向的对象。 智能指针需要相同的行为。因此std::unique_ptr::getconst方法,但不强制返回指向const对象的指针。

另请注意,您可以指向const对象。

MyClass *pointerToObject
std::unique_ptr<MyClass> smartPointerToObject;

// but you can have also a case
const MyClass *pointerToConstObject
std::unique_ptr<const MyClass> smartPointerToConstObject;

在最后一种情况下,std::unique_ptr::get将返回您期望的内容。

<小时/> 基于以下评论:

只提供私人方法:

InnerClass& GetField() { return *uniquePtrToInnerClass; }
const InnerClass& GetField() const { return *uniquePtrToInnerClass; }

在你的代码中使用它,你将在const方法中拥有内部类的const对象。

答案 3 :(得分:0)

我认为这种担忧是正确的, 每个解引用功能应该有2个版本,

e.g.
    const T* get() const;
    T* get();
    enter code here

我知道提供“ T * get()const”的目的是为了轻松替换现有的原始指针用法。

但是由于uniq ptr表示所有权,因此某些人能够通过不可变(const)引用修改该对象自己拥有的某些东西是不正确的[假设修改某个对象完全拥有的东西与修改对象本身相同-如果这是对象而不是ptr,则为true。

也许最好的选择是提供标准版本的Uniq ptr并保持上述习语(唯一的选择可能是从uniq ptr派生一个新类并提供2个版本用于取消引用)