C字符串映射键

C string map key

本文关键字:映射 字符串      更新时间:2023-10-16

使用C字符串作为映射键有问题吗?

std::map<const char*, int> imap;

元素在映射中的顺序无关紧要,所以如果使用std::less<const char*>对它们进行排序也没关系。

我使用的是Visual Studio,根据MSDN(特定于微软):

在某些情况下,可以"合并"相同的字符串文字以节省可执行文件中的空间。在字符串文字池中,编译器会使对特定字符串文字的所有引用指向内存中的同一位置,而不是让每个引用指向字符串文字的单独实例。

它说它们只在某些情况下被合并,所以使用字符串文字访问映射元素似乎是个坏主意:

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

是否可以为const char*重载operator==,以便使用实际的C字符串而不是指针值来确定映射元素是否相等:

bool operator==(const char* a, const char* b)
{
return strcmp(a, b) == 0 ? true : false;
}

使用C字符串作为映射键是个好主意吗?

是否可以为const char*重载运算符==,以便使用实际的C字符串而不是指针值来确定映射元素是否等于

不,是的,这不是一个好主意,原因正是问题中指出的,因为您不需要char*,所以可以使用std::string。(正如simonc所指出的,你可以提供一个自定义的比较函数,但我建议不要这样做)

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

是的,它们甚至可以引用还不存在的元素,但它们将由operator[]创建并进行值初始化。分配也存在同样的问题:

imap["hello"] = 0;
imap["hello"] = 1;

地图现在可能有1或2个元素。

您可以提供一个带有自定义比较器的映射,用于比较C字符串

std::map<const char*,YourType,CstrCmp>;
bool CstrCmp::operator()(const char* a, const char* b) const
{
return strcmp(a, b) < 0;
}

首先,为了在映射键上引入排序,您需要定义一个"小于"的比较。地图上说,如果两个元素都不小于另一个,那么这两个元素就是"等价的"。使用char*作为映射键是个坏主意,因为您需要在映射之外的某个地方进行内存管理。

在大多数现实场景中,当您查询地图时,您的键将不是文字。

另一方面,如果您自己维护一个字符串文字池,并为每个文字分配一个ID,则可以将这些ID用于映射键。

总之,我不会相信微软会说"在某些情况下,文字可能会被合并"。如果用文字填充映射,并且用文字作为键查询映射,那么还可以使用enum作为键。