到不可变类型的共享指针具有值语义 [英] Shared pointer to an immutable type has value semantics

查看:121
本文介绍了到不可变类型的共享指针具有值语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Sean Parent在Going Native 2013上发表了一篇题为继承的演讲是邪恶的基础类。在20分钟,50秒,他做出了一个指向不可变(const)类型( std :: shared_pointer< const T> )的共享指针具有值语义的陈述。这到底是什么意思?为什么它不同于可变(非常量)类型的共享指针( std :: shared_pointer )?

解决方案

很遗憾,像 Going Native 2013 ,它受到非常紧张的时间表限制。幸运的是,对于我们来说,Sean Parent去年在C ++ Now上做了一个更彻底的讨论,名为 Value语义和基于概念的多态性 。它涵盖相同的材料,并可能回答你的问题。



简介



有两种类型的语义类型可以具有:




  • 价值语义。

  • 引用语义。 (有时称为指针语义。)



有可能继续讨论两个不同的页面,另一个。让我们简单地说使用值类型的代码可以更容易地推理。



这就是说,任何不可预测的事情发生在任何时候值类型的实例 - 不能用引用类型保证的,因为引用的值在代码的其他部分之间共享,它们引用它。



换句话说:引用类型不太可预测,因为它们可以被远程代码段更改。例如,您调用的函数可以更改从下引用的值。或者,更糟的是,如果涉及线程,则引用类型可以在任何时间由恰好对参考值操作的另一线程改变。出于这个原因,Sean Parent提出了 a shared_ptr 与全局变量一样好的说法,使用一个。



有了这一切,我们应该准备好回答手头的问题。






问题与答案



对于值类型 T ,为什么 shared_ptr< const T> 就像一个值类型,即使它是一个指针类型吗?



因为我们不能对指向的 const T 进行更改,所以关于指针/引用类型的所有内容都不太可预测不再适用。我们不再需要担心 T 意外更改,因为它是一个常量值类型。



如果我们确实想要改变 T ,我们必须复制一份,剩下的还有 shared_ptr< const T> / code>不受我们的操作影响。此外,该副本甚至可以使用一种称为写时复制的机制隐藏在值类型中,这似乎是






我认为我已经回答了Sean Parent的问题C ++现在介绍),但让更多的进一步与附录.....



一个大附录:



(感谢 @BretKuhns 提出此问题,并在评论中提供示例。)



这个整体概念有一个。叨的错误。说的 shared_ptr< const T> 表现得像一个值类型不是必然正确,除非我们知道所有的活指针/引用 T const 。这是因为 const 修饰符是单向街道 - 持有 shared_ptr 可能会阻止 us 修改 T 的实例,但不会阻止某人修改 / code>通过指针/引用非 const



知道这一点,对于 shared_ptr< const T> 这样宽泛的陈述是非常困难的,除非我知道它所有的活指针都是 const 。但是,知道这样的事情需要全局知识围绕所有使用 shared_ptr< const T> 的代码 - 对于值类型不会有问题。因此,可能更有意义的是: A shared_ptr< const T> 可用于支持值语义 p>




在旁注中,我其实是在Going Native 2013 - 也许你可以看到我的头


Sean Parent gave a talk at Going Native 2013 titled Inheritance Is The Base Class of Evil. At 20 minutes, 50 seconds in, he makes the statement that a shared pointer to an immutable (const) type (std::shared_pointer<const T>) has value semantics. What exactly does this mean? Why is it any different than a shared pointer to a mutable (non-const) type (std::shared_pointer<T>)?

解决方案

Unfortunately, like all of the talks at Going Native 2013, it was constrained by a very tight time schedule. Fortunately for us, though, Sean Parent gave a much more thorough talk last year at C++Now called Value Semantics and Concepts-based Polymorphism. It covers the same material and will probably answer your questions. I'll take a shot at explaining anyway....

Introduction

There are two types of semantics that a type can have:

  • Value semantics.
  • Reference semantics. (Sometimes called pointer semantics.)

It is possible to go on for many pages about how the two differ and when one is preferable to the other. Let's simply say that code using value types can be more easily reasoned about.

That is to say that nothing unpredictable happens at any point to an instance of a value type -- something that cannot be guaranteed with a reference type since the value that is referenced is shared between other parts of your code that hold a reference to it.

In other words: reference types are less predictable because they can be changed by a distant piece of code. For example, a function that you call could change the value referenced out from under you. Or, even worse, if threading is involved, the reference type could be changed at any time by another thread that happens to operate on the value referenced. For this reason, Sean Parent makes the statement that a shared_ptr is as good as a global variable when it comes to being able to reason about code that uses one.

With all of that said, we should be prepared to answer the question at hand.


Question and Answer

For a value type T, why does a shared_ptr<const T> act like a value type even though it is a pointer type?

Because we cannot make changes to the const T that is pointed to, everything that was said about pointer/reference types being less predictable no longer applies. We no longer have to worry about the T being changed unexpectedly because it is a const value type.

If we did want to make a change to the T, we would have to make a copy of it, leaving others that hold a shared_ptr<const T> unaffected by our actions. Moreover, the copy can even be hidden inside a value type using a mechanism called Copy-on-write, which seems to be what Sean Parent ultimately did.


I think I've answered the question as Sean Parent would (and did in the linked C++Now presentation), but lets go a bit further with an addendum.....

A Big Addendum:

(Thanks to @BretKuhns for bringing this up and providing an example in the comments.)

There is one nagging thing wrong with this whole notion. Saying that shared_ptr<const T> behaves like a value type is not necesarily correct unless we know that all living pointers/references to that instance of T are const. This is because the const modifier is a one way street -- holding a shared_ptr<const T> may prevent us from modifying the instance of T, but does not prevent somebody else from modifying the T through a pointer/reference to non-const.

Knowing this, I would be weary of making the broad statement that shared_ptr<const T> is as good as a value type unless I knew that all living pointers to it are const. But, knowing such a thing requires global knowledge of the code around all usages of shared_ptr<const T> -- something that would not be a problem for a value type. For that reason, it might make more sense to say something like: A shared_ptr<const T> can be used to support value semantics.


On a side note, I was actually at Going Native 2013 -- maybe you can see the back of my head in the front left.

这篇关于到不可变类型的共享指针具有值语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆