C++ 确定对象是否在std::集合中

C++ 确定对象是否在std::集合中,c++,stl,set,C++,Stl,Set,我试图确定对象是否已包含在std::set中。根据msdn(和其他来源),如果set::find函数没有找到您请求的元素,它应该返回end() 但是,当我实现如下代码时,set::find反而返回垃圾(0xbaadf00d) set单元集; 单元格*单元格=新单元格(); if(cellSet.find(cell)=cellSet.end()) { ... } 我用得对吗?我在VisualC++ 2005中工作。< /P> < P>是否调用了CalSt集?Enter()?也有0xBAdffd值

我试图确定对象是否已包含在
std::set
中。根据msdn(和其他来源),如果set::find函数没有找到您请求的元素,它应该返回
end()

但是,当我实现如下代码时,
set::find
反而返回垃圾(
0xbaadf00d

set单元集;
单元格*单元格=新单元格();
if(cellSet.find(cell)=cellSet.end())
{
...
}
我用得对吗?我在VisualC++ 2005中工作。< /P> < P>是否调用了CalSt集?Enter()?也有0xBAdffd值?

编辑

我在VS2008中运行了这个示例代码,一切都按预期运行。find函数返回一个指向原始值的迭代器


你到底看到了什么行为?它是返回end()还是返回集合中的另一个位置?

如果
,则您发布的代码将始终执行
中的代码,并且
0xbaadf00d
是实现的“结束后一个”标记。

尝试编译并运行您提供的代码片段,我保证你会发现它执行起来没有问题。这个问题几乎可以肯定是由于程序中其他地方发生的内存分配错误造成的,例如引用未初始化的指针或指向已删除的对象的指针


<> P>你熟悉C++容器如何管理他们的对象吗?他们不会为你删除指针。在可能的情况下,使用对象的容器而不是指向对象的指针总是比较安全的。(在某些情况下,指针的容器是必要的——特别是当您希望容器存储来自单个类层次结构的不同类型的对象时。)

使用stl集合时,我喜欢使用函数来确定成员身份。我认为这使代码更容易阅读

set<Cell*> cellSet;

Cell* cell = new Cell();    

if (cellSet.count(cell) == 0)
{
    ...
}
set单元集;
单元格*单元格=新单元格();
if(cellSet.count(cell)==0)
{
...
}

一个简单的错误是,您应该测试不等于end

set<Cell*> cellSet;
Cell* cell = new Cell();
if (cellSet.find(cell) != cellSet.end())     // Test NOT EQUAL to end
{
     // Found item in set.
}
set单元集;
单元格*单元格=新单元格();
if(cellSet.find(cell)!=cellSet.end())//测试不等于end
{
//在集合中找到项。
}
但您也应该注意,您并不是在比较实际的单元格值,而是指向单元格对象的指针(这可能是您想要的,也可能不是您想要的)。通常在C++中,你不倾向于在容器中存储指针,因为指针没有隐含的所有权,但有时是可以的。 要实际比较对象,需要使用find_if()并传递谓词(函子)

struct PointerCellTest
{
Cell&m_lhs;
PointerCellTest(Cell*lhs):m_lhs(lhs){}
布尔运算符()(单元格*rhs)
{
返回左侧。==右侧。
}
};
if(find_if(cellSet.begin()、cellSet.end()、PointerCellTest(cell))!=cellSet.end())
{
//在集合中找到项。
}

确实如此,但如果我尝试在它们之间执行==操作,它就会崩溃,而且我无论如何也不能依赖该值,因为它只是一个调试标志。在发布模式下,它们将包含两个随机值。如果找到对象,它将返回正确的迭代器;如果没有找到,则返回指向0xbaadf00d的迭代器t@Kevin,只要end()==0xbaadf00d,这应该是正确的行为。@凯文:等一下,你还在用find()的返回值做什么吗当它什么也找不到的时候?@j_random_hacker:不,我不是在用它做任何事情,而是把它和结尾进行比较。结果证明我的代码工作正常,崩溃来自其他地方。是的,显然是,显然崩溃来自其他地方,因为在移动一些东西之后,它现在似乎工作正常。它的发音和几乎有意义的事实表明它是故意的坏值。由于这个原因,0xdeadbeef作为一个规范的坏值或未初始化值很受欢迎。您的意思是发布的代码应该始终在if中执行代码吗?cellSet为空(在发布的代码中未执行任何插入),并且单元格是新的(即使已执行插入,也不可能在cellSet中),因此cellSet.find(cell)应始终返回cellSet.end()。只是想弄清楚。@Naaff:在最初的帖子中,有一个cellSet.insert(cell)中间。我会调整我的答案。在这种情况下,这套设备被临时使用,所以应该没问题。如果这是一个长期的事情,它会被设置。我不知道find_if,谢谢!下次我会记得的。很棒的方法,为什么我没想到呢?:)调用count()需要检查每个元素,而find()只在元素不存在时检查每个元素。所以find()会更快。如果要考虑可读性,最好编写一个内联函数is_成员,该函数接受一个关联容器和一个元素,并返回find()==end()。@Mark Ruzon:对于std::set,两者都具有对数复杂性。事实上,对于GNU stdlibc++,count的实现基本上是:{return find(x)==end()?0:1;}Mark所说的对于多集是正确的,但这是一个集合。因此,我想这取决于所讨论的代码是否着眼于将其推广到集合之外。我相信Scott Meyers也在有效的STL中推荐了这种方法
set<Cell*> cellSet;
Cell* cell = new Cell();
if (cellSet.find(cell) != cellSet.end())     // Test NOT EQUAL to end
{
     // Found item in set.
}
struct PointerCellTest
{
    Cell&  m_lhs;
    PointerCellTest(Cell* lhs): m_lhs(lhs) {}
    bool operator()(Cell* rhs)
    {
         return lhs.<PLOP> == rhs.<PLOP>
    }
};


if(find_if(cellSet.begin(),cellSet.end(),PointerCellTest(cell)) != cellSet.end())
{
     // Found item in set.
}