[英]C++ STL Set: Cannot find() last element inserted
我正在編寫一個使用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單元測試的代碼審查。
以下是有關完整應用程序本身中的代碼的一些要點。
您的比較函數是錯誤的-它返回bool
,而不是strcmp(3)
整數。 return語句應類似於:
return strcmp( f1->getFile(), f2->getFile() ) < 0;
在這里看看。
另外,出於好奇,為什么不只使用std::set<std::string>
呢? STL實際上具有不錯的默認設置,使您擺脫了很多手動內存管理。
在我看來,您的FileInfo
不能正常工作(至少在std::set
)。 要存儲在std::set
,比較函數應返回一個bool
值,指示兩個參數的順序為( true
)或順序為( false
)。
鑒於FileInfo
功能(對std::string
不良設計模仿),如果沒有它,您可能會更好。 據我所知,您可以在其位置使用std::string
而不損失任何功能。 您也無緣無故地使用了很多動態分配(並且泄漏了很多分配的資源)。
#include <set>
#include <iostream>
#include <iterator>
#include <string>
int main() {
char *inputs[] = { "/export/home/lm/profile", "/export/home/lm/shell", "/export/home/lm/mail" };
char *outputs[] = {"Found: ", "Could **not** find: "};
std::set<std::string> MySet(inputs, inputs+3);
for (int i=0; i<3; i++)
std::cout
<< outputs[MySet.find(inputs[i]) == MySet.end()]
<< inputs[i] << "\n";
std::copy(MySet.begin(), MySet.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
編輯:即使(或實際上, 尤其是當 ) FileInfo
更復雜時,也不應嘗試自行重新實現字符串功能。 它仍應使用std::string
作為文件名,並實現與之配合使用的operator<
:
class FileInfo {
std::string filename;
public:
// ...
bool operator<(FileInfo const &other) const {
return filename < other.filename;
}
FileInfo(char const *name) : filename(name) {}
};
std::ostream &operator(std::ostream &os, FileInfo const &fi) {
return os << fi.filename;
}
int main() {
// std::set<std::string> MySet(inputs, inputs+3);
std:set<FileInfo> MySet(inputs, inputs+3);
// ...
std::copy(MySet.begin(), MySet.end(),
std::ostream_iterator<FileInfo>(std::cout, "\n"));
}
在您的構造函數中:
FileInfo( const FileInfo & file )
{
setFile( file.getFile() );
}
m_fileName
似乎未初始化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.