【问题标题】:Is it safe to use const char * literal as a std::map key?使用 const char * 文字作为 std::map 键是否安全?
【发布时间】:2017-05-13 09:20:13
【问题描述】:

我有类,每个类都返回它的名字

struct IFoo {
    virtual const char * GetName() const = 0;
}

struct Foo : IFoo {
   const char * GetName() const { return "Foo"; }
}

struct Bar: IFoo {
   const char * GetName() const { return "Bar"; }
}

还有其他地方:

Foo* a = new Foo();
Foo* b = new Foo();

std::map<const char *, int> data;
data[a->GetName()] = 0;
printf("%i", data[b->GetName()]);

字符串文字应该存储在内存中的一个位置,但它是 100% 的吗?这段代码在 gcc 中工作,但我不确定它的多平台性。

【问题讨论】:

  • 是的,这是安全的,事实上,C++ 标准中专门添加了条款,以便这样工作
  • 这是安全的,只要您调用operator [] 并得到GetName() 的结果。如果您尝试使用来自另一个翻译单元的硬编码"Foo" 调用它,则无法保证结果。在gcc 上它会起作用,因为它默认合并常量池。
  • 非常相关,几乎重复:String Literal address across translation units
  • 我不会那样做,IMO 这是脆弱的代码。如果派生类的实现后来更改为返回指向动态分配的字符串的指针,那么您可能突然有两个相同的字符串,在std::map 中比较不同,因为它们的指针不同。
  • 就个人而言,我会选择使用std::string 键的更强大的解决方案,除非您将其描述为主要瓶颈。根据我的经验,短 std::string 键(最多 10 个字符)并不比指针键慢很多,尤其是在指针为 8 个字节进行比较的 64 位平台上。

标签: c++ c++11 key stdmap string-literals


【解决方案1】:

使用const char * 文字作为std::map 键是否安全?

是的。

但是,考虑到这不能保证找到您的对象(但可能,取决于实现):

data["Foo"]

这保证找不到你的对象:

char[] str = "Foo";
data[str];

使用基于std::strcmp 的自定义地图比较器将允许上述两种情况。

那么剩下的唯一陷阱就是可能将指向本地缓冲区的指针存储到映射中,这将超过本地缓冲区。如果您只存储字符串文字当然不会发生这种情况,但这是您在使用地图时必须记住的事情。 std::string 键不会有这样的警告。

【讨论】:

    猜你喜欢
    • 2018-11-09
    • 1970-01-01
    • 2011-05-08
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    相关资源
    最近更新 更多