【问题标题】:std::map with std::string* as key以 std::string* 为键的 std::map
【发布时间】:2014-03-09 00:41:43
【问题描述】:

我正在使用 std::mapconst std::string 键,我认为避免将键推到堆栈周围会很好,所以我将键类型更改为指针:

class less_on_star : less<const string*> {
  public:
    virtual bool operator() (const string* left, const string *right);
};

less_on_star::operator() (const string* left, const string *right) {
  return *left < *right;
}

class Foo {
  private:
    map<const string*, Bar*, less_on_star> bars;
}

它工作了一段时间,然后我开始遇到字符串键失去胆量的段错误。 _M_p 字段指向 NULL0x2,但当我插入地图时,键始终完好无损:

bars[new string(on_stack_string)] = bar;

在 gdb 中,new string(on_stack_string) 似乎将_M_p 字段指向正常的堆位置,而不是堆栈值。 std::string 有什么特别之处,它不能用在这样的数据结构中吗?也许我用钥匙做了一些其他愚蠢的事情,但我想不出它会是什么。

【问题讨论】:

  • std::string 在内部使用堆分配的内存来存储字符数据。在 g++ 中,sizeof(std::string) 是 24。因此,当您“认为避免将键推到堆栈周围会很好”时,您肯定在考虑其他事情。至于这个错误,可能和g++的copy on write有关。我敢打赌,非指针字符串会离开作用域并删除堆数据,因为指针字符串仅用作临时字符串且从未写入。
  • 你是如何跟上字符串的?似乎您可能没有正确地重新计算字符串。也许使用 shared_ptr
  • 不@KitsuneYMG,我没想到别的。我在这里问了这个问题,因为我不知道它是如何工作的。所以我需要有人向我解释,而不是因为我不知道我所问的问题而责备我。如果我知道它是如何工作的,我为什么要问它是如何工作的?

标签: c++ map segmentation-fault stdstring


【解决方案1】:

这需要一个轻量级,真的:

#include <boost/flyweight.hpp>
#include <map>

typedef boost::flyweight<std::string> string;

struct Bar
{
};

struct Foo {
    std::map<string, Bar*> bars;
};

int main()
{
    Foo foo;
    foo.bars.insert(string("hello"), new Bar());
    foo.bars.insert(string("world"), new Bar());
}

现在,为了保证Bar* 元素的安全,你为什么不使用boost::ptr_map

【讨论】:

  • 你为什么要这样做? map 不使用地址比较并且字符串是轻量级的。此外,这里没有c++11 标签。第三,由于键只在第一次插入时被复制(否则键被单独留下,它只是改变的值),使用这样的享元只会导致很多额外的副本和第二张地图保存所有钥匙,对吧?
  • @KitsuneYMG 不。你的期望是错误的。此外,那里没有特定于 C++11 的内容。
  • using string = ...emplace 是特定于 c++11 的。
  • @KitsuneYMG 好吧,感谢您指出这一点。 c++11 是该语言的当前版本。我们实际上是在 2014 年,所有编译器都支持这一点。除非问题被标记为c++03,否则我们都假设支持 c++11(可能不是某些东西,例如 MSVC 不支持)
  • @sehe 然而,提出问题处理新功能的人会标记他们的问题c++11。就好像大多数编译器还不是 c++ 编译器,并且大多数人并不常用新的语言特性。对于具有如此高声望的人,我希望有一些实际的智力和推理能力。另外,移动球门柱多吗? “那里没有特定的c ++ 11”?真的吗?
猜你喜欢
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 2012-01-06
  • 2014-12-16
  • 1970-01-01
  • 2015-10-22
  • 2012-01-12
  • 2012-06-17
相关资源
最近更新 更多