简体   繁体   English

weak_ptr C ++中的比较运算符

[英]Comparator operator in weak_ptr C++

I am still a novice in the new stl members.Can anyone point out why this code is giving segmentation fault? 我仍然是新stl成员的新手。任何人都可以指出为什么这段代码会给出分段错误?

#include<memory>
#include<stdio.h>
#include<map>
#include<set>
#include<string>
using namespace std;
struct StubClass
{
    weak_ptr<string> b;
    int c;
    friend bool operator==(StubClass x,StubClass y);
    friend bool operator<(StubClass x,StubClass y);
    StubClass(weak_ptr<string> x):b(x){c=5;}    
};
bool operator==(StubClass d,StubClass c) { return d.b==c.b;}
bool operator<(StubClass d,StubClass c) { return d.b<c.b; }


int main()
{
    shared_ptr<string> spPtr(new string("Hello"));
    weak_ptr<string> wpPtr(spPtr);
    StubClass hello(wpPtr);
    set<StubClass> helloSet;
    helloSet.insert(hello);
    if(helloSet.find(StubClass(wpPtr))!=helloSet.end()) printf("YAYA");
    else puts("Bye");
}

The error is in line 错误符合

if(helloSet.find(StubClass(wpPtr))!=helloSet.end()) printf("YAYA"); if(helloSet.find(StubClass(wpPtr))!= helloSet.end())printf(“YAYA”);

More research reveals there is a problem when the StubClass's comparator function is called. 更多的研究表明,调用StubClass的比较器函数时会出现问题。 I am compiling the program here 我在这里编译程序

EDIT: 编辑:

bool operator==(StubClass d,StubClass c) { return d.b.lock()==c.b.lock();}
bool operator<(StubClass d,StubClass c) { return d.b.lock()<c.b.lock(); }

This resolved the issue.I should be reading more.:( Anyways can anyone from the community explain the reason why the first code gives SIGSEGV.I figured it out eventually,but still a nice explanation won't hurt. :) 这解决了这个问题。我应该阅读更多。:(无论如何,社区中的任何人都可以解释第一个代码给出SIGSEGV的原因。我最终想出来了,但仍然有一个很好的解释不会受到伤害。:)

Your original code segfaults because you've accidentally set up an infinite recursion: 您的原始代码段错误,因为您不小心设置了无限递归:

bool operator<(StubClass d,StubClass c) { return d.b<c.b; }

There is no operator< for weak_ptr . 没有operator< for weak_ptr However you do have an implicit conversion from weak_ptr to StubClass . 但是,您确实有从weak_ptrStubClass的隐式转换。 And StubClass has an operator< . StubClass有一个operator< So this function calls itself indefinitely: thus the segfault. 所以这个函数无限地调用自己:因此是段错误。

The currently accepted answer from inkooboo will also lead to undefined behavior, probably resulting in a crash. 来自inkooboo的当前接受的答案也将导致未定义的行为,可能导致崩溃。 As weak_ptrs become expired during the execution of your program (something more involved than your test case), then the ordering of them will change. 由于weak_ptrs在程序执行期间过期(比测试用例更复杂),因此它们的顺序将发生变化。 When this happens between two weak_ptrs in the set , the set will become corrupted, likely leading to a crash. 当在set两个weak_ptrs之间发生这种情况时,该set将被破坏,可能导致崩溃。 However there is a way around this using owner_less which was designed specifically for this use case: 然而,有一种方法可以使用owner_less专门为此用例设计:

bool operator==(const StubClass& d, const StubClass& c)
{
    return !owner_less<weak_ptr<string>>()(d.b, c.b) &&
           !owner_less<weak_ptr<string>>()(c.b, d.b);
}
bool operator<(const StubClass& d, const StubClass& c)
{
    return owner_less<weak_ptr<string>>()(d.b, c.b);
}

Or, if you prefer, this can also be coded using the member function owner_before . 或者,如果您愿意,也可以使用成员函数owner_before进行编码。 Both are equivalent: 两者都是等价的:

bool operator==(const StubClass& d, const StubClass& c)
{
    return !d.b.owner_before(c.b) && !c.b.owner_before(d.b);
}
bool operator<(const StubClass& d, const StubClass& c)
{
    return d.b.owner_before(c.b);
}

Using these functions, even when one weak_ptr expires and the other doesn't, their ordering remains stable. 使用这些函数,即使一个weak_ptr到期而另一个没有,它们的顺序仍然稳定。 And thus you'll have a well-defined set . 因此,你将有一个明确定义的set

If you want to compare strings stored in weak_ptr do this: 如果你想比较存储在weak_ptr中的字符串,请执行以下操作:

bool operator<(StubClass d, StubClass c) 
{
    std::shared_ptr<std::string> a = d.b.lock();
    std::shared_ptr<std::string> b = c.b.lock();

    if (!a && !b)
        return false; 

    if (!a)
        return true;

    if (!b)
        return false;

    return *a < *b;
}

Run result 运行结果

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM