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

Ser*_*eyA 9 c++ string

假设我最简单std::set

std::set<std::string> my_set;
Run Code Online (Sandbox Code Playgroud)

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

bool exists(const char* str) {
    return my_set.count(str) > 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,这显然是效率损失。在这里无缘无故地发生(潜在的)动态内存分配,然后再进行释放。

我们该如何消除呢?我想与用作std::string键类型进行比较char*。一种方法是在unique_ptr<char>自定义比较器中使用而不是我的键类型,但是那样会很尴尬。

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

PS我已经看过std :: string作为map键和map.find()的效率,但是我对答案不满意,这有效地重申了不需要这种优化,尽管这显然是错误的。

Nat*_*ica 9

您是正确的,默认情况下count它将转换strstd::string可能导致动态内存分配的文件,至少会进行不必要的复制。幸运的是,C ++ 14 count以以下形式添加重载:

template< class K > 
size_type count( const K& x ) const;
Run Code Online (Sandbox Code Playgroud)

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

std::set<std::string> my_set;
Run Code Online (Sandbox Code Playgroud)

std::set<std::string, std::less<>> my_set;
// or
std::set<std::string, std::less<void>> my_set;
Run Code Online (Sandbox Code Playgroud)

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