C++ 如何在没有对象副本的情况下使用map::equal_range?

C++ 如何在没有对象副本的情况下使用map::equal_range?,c++,map,C++,Map,我有一个性能敏感函数,它使用map存储一些数据 我需要能够使用其他字符串的任何子字符串作为键来查找值,而无需创建中间字符串(即,目标是防止仅仅因为我想查找某个内容而发生堆分配) 显而易见的解决方案是保存两个独立的数据结构(可能还有另一个map,用于从某个键映射到每个字符串)——一个用于字符串,另一个用于对这些字符串的引用 但是我想知道,有没有更好的方法可以单独使用map,或者我需要另一个数据结构?如果可能的话,我希望避免创建太多额外的间接寻址。如果我误解了,很抱歉,但是如果您可以使用查询字符串的

我有一个性能敏感函数,它使用
map
存储一些数据

我需要能够使用其他
字符串的任何
字符串
作为键来查找值,而无需创建中间
字符串
(即,目标是防止仅仅因为我想查找某个内容而发生堆分配)

显而易见的解决方案是保存两个独立的数据结构(可能还有另一个
map
,用于从某个键映射到每个字符串)——一个用于字符串,另一个用于对这些字符串的引用


但是我想知道,有没有更好的方法可以单独使用
map
,或者我需要另一个数据结构?如果可能的话,我希望避免创建太多额外的间接寻址。

如果我误解了,很抱歉,但是如果您可以使用查询字符串的“子字符串视图”来搜索多映射,而不是普通的
std::string
对象,您的问题会得到解决吗

在这种情况下,可以使用以下内容(使用基于C++11的编码):

定义子字符串视图对象类型。它由字符串和(从、到)偏移量构成,但不复制子字符串:

class substrview
{
  std::string::const_iterator _from;
  std::string::const_iterator _to;
public:
  substrview(
       const std::string &s,
       const std::size_t from,
       const std::size_t to)
    : _from(s.begin()+from), _to(s.begin()+to)
  { }

  std::string::const_iterator begin() const
  { return _from; }

  std::string::const_iterator end() const
  { return _to; }
};

为了使用子字符串视图搜索多重映射,我建议使用

中的
std::lower_bound
std::upper_bound
方法,您需要一个
字符串ref
类型,该类型参与
但它找不到键“fo”@DenisErmolin是,true,在本例中,我只针对后缀实现了搜索例程,而不是针对所有子字符串。对所有的子字符串都这样做很简单;然而,搜索所有子字符串的整个想法提出了一些与“子字符串视图”问题无关的问题。特别是,当您要查找扩展字符串“abcd”的匹配项时,如何在查找某些子字符串“abc”的匹配项后“继续”搜索的问题。后者的比赛显然是前者比赛的一个子范围;理想情况下,我们应该利用这一点。
int main()
{
  std::multimap<std::string,int> map {
    { "hello" , 1 },
    { "world" , 2 },
    { "foo" , 3 },
    { "foobar" , 4 },
    { "foo" , 5 },
  };

  std::string query { "barfoo" };
  /* Search for all suffixes of "barfoo", one after the other: */
  for (std::size_t i = 0 ; i < query.size() ; ++i) {
    substrview subquery { query,i,query.size() };
    auto found_from = std::lower_bound(begin(map),end(map),subquery,cmpL);
    auto found_to   = std::upper_bound(begin(map),end(map),subquery,cmpU);

    /* Now [found_from,found_to) is the match range in the multi-map.
       Printing the matches: */
    while (found_from != found_to) {
      std::cout << found_from->first << ", " << found_from->second << '\n';
      ++found_from;
    }

  }
}
inline bool cmpL(
    const std::pair<std::string,int> &entry,
    const substrview                 &val)
{
  return std::lexicographical_compare
    (entry.first.begin(),entry.first.end(),val.begin(),val.end());
}

inline bool cmpU(
   const substrview                 &val,
   const std::pair<std::string,int> &entry)
{
  return std::lexicographical_compare
    (val.begin(),val.end(),entry.first.begin(),entry.first.end());
}
string_ref(const std::string &s): begin(s.begin()), end(s.end()) {}