std::shared_ptr::unique()
的技术问题是什么导致它在 C++17 中被弃用?
根据cppreference.com , std::shared_ptr::unique()
在 C++17 中被弃用为
this function is deprecated as of C++17 because
use_count
is only an approximation in multi-threaded environment.
我理解这对于 use_count() > 1
是正确的:当我持有对它的引用时,其他人可能同时放开他的引用或创建一个新拷贝。
但如果 use_count()
返回 1(这是我在调用 unique()
时感兴趣的内容),则没有其他线程可以更改该值以一种活泼的方式,所以我希望这应该是安全的:
if (myPtr && myPtr.unique()) {
//Modify *myPtr
}
我自己搜索的结果:
我找到了这个文件:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0521r0.html它提议弃用以响应 C++17 CD 评论 CA 14,但我找不到该评论本身。
作为替代方案,该论文建议添加一些注释,包括以下内容:
Note: When multiple threads can affect the return value of
use_count()
, the result should be treated as approximate. In particular,use_count() == 1
does not imply that accesses through a previously destroyedshared_ptr
have in any sense completed. — end note
我知道当前指定 use_count()
的方式可能是这种情况(由于缺乏保证同步),但为什么解决方案不仅仅是指定这种同步,因此使上述模式安全吗?如果存在不允许此类同步的基本限制(或使其代价高昂),那么如何正确实现析构函数?
更新:
我忽略了@alexeykuzmin0 和@rubenvb 提出的明显案例,因为到目前为止我只在其他线程无法访问的shared_ptr
实例上使用了unique()
他们自己。因此,该特定实例不会以不正当的方式被复制。
我仍然有兴趣了解 CA 14 到底是什么,因为我相信我的所有 unique()
用例只要保证与发生的任何事情同步就可以工作其他线程上的不同 shared_ptr
实例。所以它对我来说似乎仍然是一个有用的工具,但我可能会在这里忽略一些基本的东西。
为了说明我的想法,请考虑以下内容:
class MemoryCache {
public:
MemoryCache(size_t size)
: _cache(size)
{
for (auto& ptr : _cache) {
ptr = std::make_shared<std::array<uint8_t, 256>>();
}
}
// the returned chunk of memory might be passed to a different thread(s),
// but the function is never accessed from two threads at the same time
std::shared_ptr<std::array<uint8_t,256>> getChunk()
{
auto it = std::find_if(_cache.begin(), _cache.end(), [](auto& ptr) { return ptr.unique(); });
if (it != _cache.end()) {
//memory is no longer used by previous user, so it can be given to someone else
return *it;
} else {
return{};
}
}
private:
std::vector<std::shared_ptr<std::array<uint8_t, 256>>> _cache;
};
有什么问题吗(如果 unique()
实际上会与其他拷贝的析构函数同步)?
最佳答案
考虑以下代码:
// global variable
std::shared_ptr<int> s = std::make_shared<int>();
// thread 1
if (s && s.unique()) {
// modify *s
}
// thread 2
auto s2 = s;
这里我们有一个经典的竞争条件:s2
可能(也可能不会)在线程 2 中创建为 s
的拷贝,而线程 1 在 如果
.
unique() == true
表示没有人有一个 shared_ptr
指向同一个内存,但并不意味着任何其他线程无权访问初始 shared_ptr
直接或通过指针或引用。
关于c++ - 为什么不推荐使用 std::shared_ptr::unique() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41142315/