bas*_*hrc 4 c++ stl weak-ptr c++11
我仍然是新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");
}
Run Code Online (Sandbox Code Playgroud)
错误符合
if(helloSet.find(StubClass(wpPtr))!= helloSet.end())printf("YAYA");
更多的研究表明,调用StubClass的比较器函数时会出现问题.我在这里编译程序
编辑:
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(); }
Run Code Online (Sandbox Code Playgroud)
这解决了这个问题.我应该阅读更多.:(无论如何,社区中的任何人都可以解释第一个代码给出SIGSEGV的原因.我最终想出来了,但仍然有一个很好的解释不会受到伤害.:)
您的原始代码段错误,因为您不小心设置了无限递归:
bool operator<(StubClass d,StubClass c) { return d.b<c.b; }
Run Code Online (Sandbox Code Playgroud)
没有operator<了weak_ptr.但是你有从隐式转换weak_ptr到StubClass.并StubClass有一个operator<.所以这个函数无限地调用它自己:因此是段错误.
来自inkooboo的当前接受的答案也将导致未定义的行为,可能导致崩溃.由于weak_ptrs在程序执行期间过期(比测试用例更复杂),它们的顺序将发生变化.发生这种情况时两者之间weak_ptrs的set,则set将会被破坏,可能导致崩溃.然而,有一种解决方案可以使用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);
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您愿意,也可以使用成员函数对其进行编码owner_before.两者都是等价的:
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);
}
Run Code Online (Sandbox Code Playgroud)
使用这些功能,即使一个weak_ptr到期而另一个没有,它们的顺序仍然稳定.因此你将有一个明确的定义set.