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()) {}