gpt4 book ai didi

C++ STL 集 : Cannot find() last element inserted

转载 作者:塔克拉玛干 更新时间:2023-11-03 08:14:23 26 4
gpt4 key购买 nike

我正在编写一个使用 C++ STL 中的 Set 类的应用程序。我发现当我查询我插入的最后一个元素时,对 set->find() 的调用似乎总是失败。但是,如果我遍历该集合,我就能看到我最初查询的元素。

为了尝试了解问题出在哪里,我创建了一个示例应用程序,它表现出与我所看到的相同的行为。我的测试代码贴在下面。

对于实际的应用程序本身,我需要在集合中存储指向对象的指针。这是导致奇怪行为的原因吗?或者是否有一个运算符需要在我存储指针的类中重载?

如有任何帮助,我们将不胜感激。

#include <stdio.h>
#include <set>

using namespace std;

#define MySet set<FileInfo *,bool(*)(const FileInfo *, const FileInfo*)>

class FileInfo
{
public:
FileInfo()
{
m_fileName = 0;
}
FileInfo( const FileInfo & file )
{
setFile( file.getFile() );
}
~FileInfo()
{
if( m_fileName )
{
delete m_fileName;
m_fileName = 0;
}
}
void setFile( const char * file )
{
if( m_fileName )
{
delete m_fileName;
}
m_fileName = new char[ strlen( file ) + 1 ];
strcpy( m_fileName, file );
}
const char * getFile() const
{
return m_fileName;
}
private:
char * m_fileName;
};

bool fileinfo_comparator( const FileInfo * f1, const FileInfo* f2 )
{
if( f1 && ! f2 ) return -1;
if( !f1 && f2 ) return 1;
if( !f1 && !f2 ) return 0;

return strcmp( f1->getFile(), f2->getFile() );
}

void find( MySet *s, FileInfo * value )
{
MySet::iterator iter = s->find( value );
if( iter != s->end() )
{
printf( "Found File[%s] at Item[%p]\n", (*iter)->getFile(), *iter );
}
else
{
printf( "No Item found for File[%s]\n", value->getFile() );
}
}

int main()
{
MySet *theSet = new MySet(fileinfo_comparator);

FileInfo * profile = new FileInfo();
FileInfo * shell = new FileInfo();
FileInfo * mail = new FileInfo();

profile->setFile( "/export/home/lm/profile" );
shell->setFile( "/export/home/lm/shell" );
mail->setFile( "/export/home/lm/mail" );

theSet->insert( profile );
theSet->insert( shell );
theSet->insert( mail );

find( theSet, profile );

FileInfo * newProfile = new FileInfo( *profile );

find( theSet, newProfile );

FileInfo * newMail = new FileInfo( *mail );

find( theSet, newMail );

printf( "\nDisplaying Contents of Set:\n" );
for( MySet::iterator iter = theSet->begin();
iter != theSet->end(); ++iter )
{
printf( "Item [%p] - File [%s]\n", *iter, (*iter)->getFile() );
}
}

我从中得到的输出是:

Found File[/export/home/lm/profile] at Item[2d458]
Found File[/export/home/lm/profile] at Item[2d458]
No Item found for File[/export/home/lm/mail]

Displaying Contents of Set:
Item [2d478] - File [/export/home/lm/mail]
Item [2d468] - File [/export/home/lm/shell]
Item [2d458] - File [/export/home/lm/profile]

**编辑我不得不添加这个有点难过。但正如我之前提到的,这是一个示例应用程序,它是从一个更大的应用程序的不同部分提取的,以展示我收到的失败。

它是一个单元测试,用于在填充有堆分配指针的集合上调用 set::find。如果您对所有 new() 有疑问,我乐于接受有关如何在不使用堆分配指针的情况下神奇地填充集合的建议。否则评论“太多的 new() 调用”只会让你看起来很傻。

请关注实际发生的问题(现已解决)。谢谢。

***编辑

也许我应该把这些放在我原来的问题中。但我希望更多地关注 find() 的问题(或者事实证明 fileinfo_comparator 函数更像 strcmp 而不是更少),然后是复制粘贴 PoC 单元测试的代码审查。

以下是有关完整应用程序本身代码的一些要点。

  • FileInfo 包含大量数据和文件名。它包含 SHA1 总和、文件大小、修改时间、上次编辑时的系统状态等。我已经删除了这篇文章的代码。它违反了这种形式的 3 法则(感谢@Martin York。请参阅 wiki 链接的评论)。
  • 最初选择使用 char* 而不是 std::string 是因为使用了接受 char* 的第 3 方 API。该应用程序从那时起就发展了。改变这不是一种选择。
  • FileInfo 中的数据从系统上的命名管道轮询,并存储在单例中以供跨多个线程访问。 (如果我不在堆上分配,我会遇到范围问题)
  • 我选择将指针存储在 Set 中,因为 FileInfo 对象很大并且不断地从 Set 中添加/删除。我认为指针比总是将大型结构复制到 Set 中要好。
  • 我的析构函数中的 if 语句是不必要的,它是调试我正在追踪的问题时遗留下来的工件。它应该被拉出来,因为它不需要。

最佳答案

你的比较函数是错误的 - 它返回 bool , 不是整数 strcmp(3) .返回语句应该是这样的:

return strcmp( f1->getFile(), f2->getFile() ) < 0;

看看here .

此外,出于好奇,为什么不直接使用 std::set<std::string>反而? STL 实际上有不错的默认值,可以让您从大量手动内存管理中解放出来。

关于C++ STL 集 : Cannot find() last element inserted,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3453256/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com