我正在編寫一個應用程序,我在其中使用C++ STL中的Set類。我發現,當我查詢插入的最後一個元素時,對set-> find()的調用總是失敗。但是,如果我遍歷該集合,則可以看到最初查詢的元素。C++ STL Set:無法找到()插入的最後一個元素
爲了弄清楚什麼是錯誤的,我創建了一個示例應用程序,展現出與我所看到的相同的行爲。我的測試代碼發佈在下面。
對於實際應用程序本身,我需要存儲指向集合中對象的指針。這是什麼造成了怪異的行爲。或者是否有我需要在類中重載的操作符?我正在存儲指針?
任何幫助,將不勝感激。
#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()(或者因爲它變成更像strcmp的fileinfo_comparator函數比less更少)的問題會更加關注,然後是複製粘貼PoC單元測試的代碼審查。
下面是關於完整應用程序本身的代碼的一些觀點。
- FileInfo保存了大量的數據以及文件名。它包含SHA1總和,文件大小,模式時間,最後編輯的系統狀態等。我已經刪除了這個帖子的代碼。它以這種形式違反了規則3(感謝@Martin York。請參閱維基鏈接的評論)。
- 由於使用接受char *的3rd_party API,最初選擇使用char *而不是std :: string。該應用程序已經從那時起發展。改變這不是一個選項。
- FileInfo中的數據是從系統上的命名管道輪詢的,並存儲在Singleton中以便跨多個線程訪問。 (如果我沒有在堆上分配,我會遇到範圍問題)
- 我選擇將指針存儲在Set中,因爲FileInfo對象很大並且不斷地從Set中被添加/刪除。我決定將指針比總是將大型結構複製到Set中要好。
- 在我的析構函數中的if語句是不必要的,並且在調試我正在追蹤的問題時遺留了工件。它應該被取消,因爲它是不需要的。
請大家看看'typedef'關鍵字 - 沒有必要使用宏來縮短類型的名稱。 – 2010-08-10 20:57:49
無關nitpick:在刪除它們之前不需要檢查null的指針。刪除空指針是安全的。 – 2010-08-10 22:00:28
爲什麼到處都是新的,這不是Java。 – 2010-08-10 23:57:59