如何在const共享指针与非const对象一起使用reset?

huangapple go评论60阅读模式
英文:

how to use reset with const shared pointer to non const object?

问题

无法将“const boost::shared_ptr<boost::log::v2s_mt_nt6::sinks::text_file_backend>”的“this”指针转换为“boost::shared_ptr<boost::log::v2s_mt_nt6::sinks::text_file_backend> &”。
此错误告诉我,不允许使用const共享指针进行重置?!! 这是真的吗?
如果是这样,我如何将这个const共享指针转换为非const以便用于重置?

英文:

I am trying to reset shared pointer which is member of struct coming from iterator of container with constant structs"elements".
the code does not compile, with error:

cannot convert &#39;this&#39; pointer from &#39;const boost::shared_ptr&lt;boost::log::v2s_mt_nt6::sinks::text_file_backend&gt;&#39; to &#39;boost::shared_ptr&lt;boost::log::v2s_mt_nt6::sinks::text_file_backend&gt; &amp;&#39;

this error tells me that const shared pointer is not allowed to be used by reset??!! is this true?
if so how can i cast this const shared pointer into non const to be used by reset??

答案1

得分: 4

如果您有一个 const shared_ptr&lt;T&gt;,那么您不能更改它指向的内容。这就是 const 的特性。因此,您不能调用 reset,因为那会改变它指向的内容。

您可以创建一个非 const 的副本,并更改它所指向的内容,但这仍然不会改变原始的 const 指针。

英文:

If you have a const shared_ptr&lt;T&gt; then you cannot change what it points to. That is the nature of const. Thus, you cannot call reset, because that would change what it points to.

You can create a non-const copy, and change what that points to, but that still won't change the original const pointer.

答案2

得分: 1

不要尝试执行任何可能删除由const shared_ptr&lt;T&gt;持有的指针的操作,比如对其调用reset()

如果你像这样做:delete myConstSharedPtr.get();,那么当引用计数达到0时,存储的指针将再次被调用delete,从而导致双重释放错误。

此外,你应该重新考虑你的设计,决定是否真的要在这里使用shared_ptr

最终,作为非常后一种选择,如果这个shared_ptrconst性来自于一个不应强加这个const限制且你无法正确修复的外部库,那么const_cast就是为这种情况而生的。但是请忘掉它,你真的不想使用它。

还在吗?以下是如何使用const_cast来强制重置const shared_ptr

template&lt;typename T&gt;
void forceReset(const std::shared_ptr&lt;T&gt; ptr){
   const_cast&lt;std::shared_ptr&lt;T&gt;&amp;&gt;(ptr).reset();
}

警告:如果这段代码乍一看就是你想要的,那意味着你依赖的坏库存在内存泄漏问题。事实上,没有办法分离一个shared_ptr,即在不更新引用计数的情况下销毁它。这意味着除非有一个指向强制删除资源的共享指针是动态分配的并且在程序结束之前从未被删除,否则将发生双重释放,导致未定义行为...很可能是严重的崩溃。

但如果你仍然想继续,绝对不应该这样做,你可以利用这一点来防止引用计数达到零,代价是小内存泄漏,该泄漏将在程序退出时清理。泄漏内存不会导致任何未定义行为。

template&lt;typename T&gt;
void forceReset(const std::shared_ptr&lt;T&gt; ptr){
   //这个泄漏的shared_ptr将阻止自动删除
   new std::shared_ptr&lt;T&gt;(ptr);
   const_cast&lt;std::shared_ptr&lt;T&gt;&amp;&gt;(ptr).reset();
}

再次声明:我强烈不建议任何人使用这个技巧。我提供它来讨论与智能指针和const_cast搞乱的风险。请再次考虑修复有问题的库或使用另一个库。

英文:

Do not attemps to do anything that could delete the pointer hold by a const shared_ptr&lt;T&gt;, like calling reset() on it!

If you do something like delete myConstSharedPtr.get();, delete will get called again on the stored pointer when the reference count will reach 0, basically causing a double free error.

Also, you should reconsider your design and decide wether shared_ptr is really what you want to use here.


Ultimately, as a very last resort, if the const'ness of this shared_ptr comes from an external library which should not impose this const restriction and which you cannot properly patch, then const_cast is made for such situation. But forget it, you don't want to use that, really.

Still there ? Here is how to use const_cast to force reset a const shared_ptr.

template&lt;typename T&gt;
void forceReset(const std::shared_ptr&lt;T&gt; ptr){
   const_cast&lt;std::shared_ptr&lt;T&gt;&amp;&gt;(ptr).reset();
}

WARNING: If this code does what you want at first sight, it means that the bad library you depend on leaks memory. Indeed, there is no way to detach a shared_ptr, that is, destroying it without updating the reference count. It means that unless one of the shared pointer referring to the force-deleted resource is dynamically allocated and never deleted until the end of the program, a double free will occur resulting in undefined behaviour... likely a nasty crash.

But if you still want to proceed, which you should definitely not, you could take advantage of that to prevent the reference counter to reach zero at the cost of a small memory leak which will be cleaned-up at program exit. Leaking memory will not lead to any kind of undefined behavior.

template&lt;typename T&gt;
void forceReset(const std::shared_ptr&lt;T&gt; ptr){
   //This leaked shared_ptr will prevent automatic deletion
   new std::shared_ptr&lt;T&gt;(ptr);
   const_cast&lt;std::shared_ptr&lt;T&gt;&amp;&gt;(ptr).reset();
}

Just another disclaimer: I strongly discourage anyone to use this hack. I gave it to discuss the risk of messing with smart pointers and const_cast. Please, consider one more time patching the offending library or using another one.

huangapple
  • 本文由 发表于 2020年1月6日 19:17:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/59611129.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定