std :: set带字符串键和潜在的效率损失

时间:2019-06-27 18:39:44

标签: c++ string

假设我的所有情况中,std::set最简单:

std::set<std::string> my_set;

现在,我有一个函数可以接受const char*,并且需要告诉我该字符串是否存在于集合中,该函数以最简单的方式实现:

bool exists(const char* str) {
    return my_set.count(str) > 0;
}

现在,这是明显的效率损失。动态内存分配(潜在的)并随后进行释放是无缘无故的。

我们如何消除这种情况?我想将要成为键类型的std::stringchar*进行比较。一种方法是在自定义比较器中使用unique_ptr<char>而不是我的键类型,但是那样会很尴尬。

实际上,该问题可以推广到更广泛的情况,“如何在不转换为键类型的情况下调用提供的类型的比较?”

P.S。我见过std::string as map key and efficiency of map.find(),但是我对答案不满意,答案有效地重申了这种优化是不必要的,尽管它显然是错误的。

1 个答案:

答案 0 :(得分:9)

您是正确的,默认情况下count会将str转换为std::string可能会导致动态内存分配,并且至少会进行不必要的复制。幸运的是,C ++ 14以{p>的形式为count添加了重载

template< class K > 
size_type count( const K& x ) const;

这可以是任何类型。为了获得此重载,尽管您需要有一个比较器来定义名称为is_transparent的成员类型(该类型无关紧要,只是它存在)。尽管我们可以使用C ++ 14中引入的新std::less<void>,但不必写一个。通过提供模板化的operator(),它可以用作透明的比较器。这意味着您只需要更改

std::set<std::string> my_set;

std::set<std::string, std::less<>> my_set;
// or
std::set<std::string, std::less<void>> my_set;

然后该集合将使用bool operator<(std::string, const char*)进行比较,而无需进行临时或复制。