我可以投射shared_ptr< T> &到shared_ptr< T const> &不更改use_count? [英] Can I cast shared_ptr<T> & to shared_ptr<T const> & without changing use_count?

查看:257
本文介绍了我可以投射shared_ptr< T> &到shared_ptr< T const> &不更改use_count?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 boost :: shared_ptr s的程序,尤其是依赖于 use_count 执行优化。



例如,假设有一个带有两个称为lhs和rhs的参数指针的加法运算。假设它们都具有 shared_ptr< Node> 类型。是时候执行加法了,我将检查 use_count ,如果我发现其中一个参数的引用计数恰好是一个,那么我将重用它以执行适当的操作。如果两个参数都不能重用,则必须分配一个新的数据缓冲区,然后就地执行该操作。我正在处理庞大的数据结构,因此就地优化非常有益。



因此,我永远无法复制 shared_ptr s没有理由,即每个函数都通过引用或const引用获取 shared_ptr s以避免扭曲 use_count

我的问题是:我有时会有一个 shared_ptr< T> & 我想转换为 shared_ptr< T const> & ,但是如何在不影响使用次数的情况下做到这一点? static_pointer_cast 返回一个新对象,而不是引用。我倾向于认为,将整个 shared_ptr 都进行转换是可行的,例如:

  void f(shared_ptr< T& x)
{
shared_ptr< T const> & x_ = * reinterpret_cast< shared_ptr< T const> *>(& x);
}

我非常怀疑这是否符合标准,但正如我所说,可能会工作。有没有一种方法可以保证安全和正确?



更新以解决问题



对设计提出疑问并没有帮助回答这篇文章。有两个有趣的问题需要考虑:


  1. 是否有任何保证(由助推器的作者进行: :shared_ptr ,或者按照标准,在 std :: tr1 :: shared_ptr 的情况下) shared_ptr< T> ; shared_ptr< T const> 具有相同的布局和行为?


  2. 如果(1)为真,那么以上内容是否合法使用reinterpret_cast?我想您很难为上面的示例找到一个生成失败代码的编译器,但这并不意味着合法。不管您的答案是什么,您都能在C ++标准中找到对它的支持吗?



解决方案

< blockquote>

有时我有一个 shared_ptr< T> & 我想转换为 shared_ptr< T const> & ,但是如何在不影响使用次数的情况下做到这一点?


您没有。这个概念是错误的。考虑裸指针 T * const T * 会发生什么。当您将 T * 转换为 const T * 时,现在有两个指针 。您没有对同一指针的两个引用;您有两个指针。



为什么智能指针应该有所不同?您有两个指针:一个指向 T ,另一个指向 const T 。它们都共享同一个对象的所有权,因此您要使用它们中的两个。因此,您的 use_count 应该为2,而不是1。



您的问题是您试图重载 use_count ,将其功能用于其他目的。简而言之:您做错了。



您对 shared_ptr s use_count 是一个... 令人恐惧的。您基本上是在说某些函数会选择其参数之一,而调用方很清楚地使用了该参数(因为调用方显然仍在使用它)。而且调用者不知道声明了哪一个(如果有),因此调用者不知道该函数后参数的状态是什么。



此外,只有在您通过 shared_ptr<时,您的操作才能正常工作。 T> ,这本身不是一个好主意(就像常规指针一样,智能指针几乎总是应按值使用)。



简而言之,您将获取一个具有明确定义的惯用法和语义的非常常用的对象,然后要求以几乎从不使用的方式使用该对象,并使用与之相反的专门语义每个人实际使用它们的方式。



您已经有效地创建了co-optable指针的概念,co-optable指针的共享指针可以处于三种使用状态:空,由仅将它提供给您的人,因此您可以从中窃取它,并且有多个人在使用它,因此您将无法拥有它。不是 shared_ptr 所支持的语义。因此,您应该编写自己的智能指针,以更自然的方式提供这些语义。



可以识别指针周围有多少实例与哪些实例之间存在差异的方法您有多少实际用户。这样,您可以按值正确传递它,但是您可以用某种方式说出您当前正在使用它,并且不希望其他功能之一声明它。它可以在内部使用 shared_ptr ,但应提供自己的语义。


I have a program that uses boost::shared_ptrs and, in particular, relies on the accuracy of the use_count to perform optimizations.

For instance, imagine an addition operation with two argument pointers called lhs and rhs. Say they both have the type shared_ptr<Node>. When it comes time to perform the addition, I'll check the use_count, and if I find that one of the arguments has a reference count of exactly one, then I'll reuse it to perform the operation in place. If neither argument can be reused, I must allocate a new data buffer and perform the operation out-of-place. I'm dealing with enormous data structures, so the in-place optimization is very beneficial.

Because of this, I can never copy the shared_ptrs without reason, i.e., every function takes the shared_ptrs by reference or const reference to avoid distorting use_count.

My question is this: I sometimes have a shared_ptr<T> & that I want to cast to shared_ptr<T const> &, but how can I do it without distorting the use count? static_pointer_cast returns a new object rather than a reference. I'd be inclined to think that it would work to just cast the whole shared_ptr, as in:

void f(shared_ptr<T> & x)
{
  shared_ptr<T const> & x_ = *reinterpret_cast<shared_ptr<T const> *>(&x);
}

I highly doubt this complies with the standard, but, as I said, it will probably work. Is there a way to do this that's guaranteed safe and correct?

Updating to Focus the Question

Critiquing the design does not help answer this post. There are two interesting questions to consider:

  1. Is there any guarantee (by the writer of boost::shared_ptr, or by the standard, in the case of std::tr1::shared_ptr) that shared_ptr<T> and shared_ptr<T const> have identical layouts and behavior?

  2. If (1) is true, then is the above a legal use of reinterpret_cast? I think you would be hard-pressed to find a compiler that generates failing code for the above example, but that doesn't mean it's legal. Whatever your answer, can you find support for it in the C++ standard?

解决方案

I sometimes have a shared_ptr<T> & that I want to cast to shared_ptr<T const> &, but how can I do it without distorting the use count?

You don't. The very concept is wrong. Consider what happens with a naked pointer T* and const T*. When you cast your T* into a const T*, you now have two pointers. You don't have two references to the same pointer; you have two pointers.

Why should this be different for smart pointers? You have two pointers: one to a T, and one to a const T. They're both sharing ownership of the same object, so you are using two of them. Your use_count therefore ought to be 2, not 1.

Your problem is your attempt to overload the meaning of use_count, co-opting its functionality for some other purpose. In short: you're doing it wrong.

Your description of what you do with shared_ptrs who's use_count is one is... frightening. You're basically saying that certain functions co-opt one of its arguments, which the caller is clearly using (since the caller obviously is still using it). And the caller doesn't know which one was claimed (if any), so the caller has no idea what the state of the arguments is after the function. Modifying the arguments for operations like that is usually not a good idea.

Plus, what you're doing can only work if you pass shared_ptr<T> by reference, which itself isn't a good idea (like regular pointers, smart pointers should almost always be taken by value).

In short, you're taking a very commonly used object with well-defined idioms and semantics, then requiring that it be used in a way that they are almost never used, with specialized semantics that work counter to the way everyone actually uses them. That's not a good thing.

You have effectively created the concept of co-optable pointer, a shared pointer that can be in 3 use states: empty, in use by the person who gave it to you only and thus you can steal from it, and in use by more than one person so you can't have it. It's not the semantics that shared_ptr exists to support. So you should write your own smart pointer that provides these semantics in a much more natural way.

Something that recognizes the difference between how many instances of a pointer you have around and how many actual users of it you have. That way, you can pass it around by value properly, but you have some way of saying that you are currently using it and don't want one of these other functions to claim it. It could use shared_ptr internally, but it should provide its own semantics.

这篇关于我可以投射shared_ptr&lt; T&gt; &amp;到shared_ptr&lt; T const&gt; &amp;不更改use_count?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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