您不能将临时 shared_ptr 插入一组弱指针,因为从这个存储的弱指针指向已删除的内存的意义上讲,这是内存泄漏。
intset.insert(make_shared<int>(1));
// after this instruction shared_ptr destructor frees the memory
这就是为什么你在 set 中找不到它 - 因为 *lhs.lock() 在这里是 UB。
见weak_ptr::lock doc。
您需要以这种方式制作您的 òrder 运算符:
struct lex_compare {
bool operator() (const weak_ptr<int> &lhs, const weak_ptr<int> &rhs)const {
auto lptr = lhs.lock(), rptr = rhs.lock();
if (!rptr) return false; // nothing after expired pointer
if (!lptr) return true; // every not expired after expired pointer
return *lptr < *rptr;
}
};
所有这意味着 - 你需要有这个 shared_ptr sowmewhere 来计算它:
int main(){
set<weak_ptr<int>,lex_compare> intset;
auto shared1 = make_shared<int>(1);
intset.insert(shared1);
cout << "intset size:" << intset.size() << endl; //1
cout << "Does 1 exist?"<< intset.count(make_shared<int>(1))<<endl; // failed
}
以上 - 你的计数将起作用。
还考虑将 shared_ptr 保留在集合中...
[更新]
cmets 中的marko 指出了有效的问题。 std::weak_ptr 根本不能以您使用它的方式用作键。仅当您可以确保指向的值永远不会改变或指针本身永远不会过期时。看这个例子:
set<weak_ptr<int>,lex_compare> intset;
auto shared1 = make_shared<int>(1);
intset.insert(shared1);
cout << "Does 1 exist?"<< intset.count(make_shared<int>(1))<<endl; // works
shared1.reset();
cout << "Does 1 exist?"<< intset.count(make_shared<int>(1))<<endl; // failed
还有另一个例子:
set<weak_ptr<int>,lex_compare> intset;
auto shared1 = make_shared<int>(1);
intset.insert(shared1);
cout << "Does 1 exist?"<< intset.count(make_shared<int>(1))<<endl; // works
*shared1 = 2;
cout << "Does 1 exist?"<< intset.count(make_shared<int>(1))<<endl; // failed
您可以保留 std::shared_ptr 以防止指针过期 - 并且 std::shared_ptr 具有 operator < - 但此运算符比较指针本身 - 而不是指向的值 - 所以更好的是 std::set<std::shared_ptr<int>> - 但最好的是std::set<int>
或更改std::set<...> --> std::vector<std::weak_ptr<int>> - 并使用count_if-- 见:
vector<weak_ptr<int>> intset;
auto shared1 = make_shared<int>(1);
intset.push_back(shared1);
cout << "Does 1 exist?"<< count_if(begin(intset), end(intset),
[](auto&& elem)
{
auto ptr = elem.lock();
return ptr && *ptr == 1;
});
或者std::set<std::shared_ptr<int>>:
set<shared_ptr<int>> intset;
auto shared1 = make_shared<int>(1);
intset.insert(shared1);
// if you can ensure shared1 value will not change:
cout << "Does 1 exist?"<< intset.count(shared1);
// if not - use count_if - the slower than std::count
cout << "Does 1 exist?"<< count_if(begin(intset), end(intset),
[](auto&& ptr)
{
return ptr && *ptr == 1;
});