快速序言,我对.Net感到非常满意,但对c ++的经验有限,所以我不确定我是否做得很好。 我正在使用文件映射对象来检索可能是一个相对较长的字符串,由多达数千个文件名组成。可以从连接到Windows资源管理器的ImageOverlayHandler调用此函数,因此速度和内存消耗都很重要。这个代码可能会被一次数百个覆盖请求调用(但仅限于边缘情况)。在下面的代码中,这是一种有效的方法吗?使用这种方法,如果我已正确理解我的代码,我将不会制作映射文件的本地副本,并且boost :: contains调用应该非常快。关于我如何改进它,或者我应该如何做到这一点的任何想法?在之前的迭代中我使用了矢量等,但这似乎会使用更多的内存。
HRESULT GetFolders()
{
HANDLE hMapFile;
LPCWSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szFolderName); // name of mapping object
if (hMapFile == NULL)
{
return NULL;
}
pBuf = (LPCWSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
CloseHandle(hMapFile);
return NULL;
}
wstring resOut = (wstring)pBuf;
bool val = boost::contains(resOut, L"C:\\FOLDER1");
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
}
答案 0 :(得分:1)
由于您将此数据描述为文件名列表,因此请考虑将每个文件名放在std::set
或std::unordered_set
(C ++ 11)或boost::unordered_set
(C ++ 03及更高版本)中)。
您的方法具有 O(n)效率。
std::set
将具有 O(log n)效率。
unordered_set
会有 O(1)效率。
注意:任何这些容器的创建都应该提前完成一次。不适用于GetFolders()
答案 1 :(得分:1)
如果您正在创建一次或仅偶尔创建文件名列表并重复测试,您可以从二进制搜索中受益。二进制搜索需要两件事:输入列表必须排序,并且您必须能够有效地索引到列表的任何元素。
在将文件写入文件之前,您可以通过在C#中对列表进行排序来满足第一个要求。您可以通过创建一个整数列表来满足第二个要求,这些整数表示每个文件名开头的字符串偏移量。由于每个整数的大小都相同,因此可以将其编入索引,并且只需一个简单的间接即可获得实际的文件名。
std::equal_range
算法将执行二进制搜索。如果返回的迭代器相等,则找不到该项,否则第一个迭代器指向它。
您需要一个自定义比较器函数传递给equal_range
来对字符串进行间接处理。