为什么std :: equal_to会导致动态分配?

lin*_*ver 20 c++ heap-memory std-pair

考虑以下简单示例,我用它std::equal_to来比较两个std::pair<std::string, unsigned>.它operator new被重载,以便在分配时打印一条消息(此处为实时代码):

#include <functional>
#include <string>
#include <iostream>

// overloaded to see when heap allocations take place
void* operator new(std::size_t n)
{
    std::cout << "Allocating " << n << std::endl;
    return malloc(n);
}

int main()
{
    using key_type = std::pair<std::string, unsigned>;
    auto key1 = std::make_pair(std::string("a_______long______string______"), 1);
    auto key2 = std::make_pair(std::string("a_______long______string______"), 1);

    std::cout << "Finished initial allocations\n\n" << std::endl;

    std::equal_to<key_type> eq;
    eq(key1, key2); // how can this cause dynamic allocation???
}
Run Code Online (Sandbox Code Playgroud)

我看到的信息是

Allocating 31
Allocating 31
Finished initial allocations


Allocating 31
Allocating 31
Run Code Online (Sandbox Code Playgroud)

你可以看到有两个分配正在发生比较时key1key2.但为什么?std::equal_to运算符通过const引用获取其参数,因此不应该进行分配...我缺少什么?谢谢.

eer*_*ika 29

这是因为你复制了这些对.

类型keyXstd::pair<std::string, int>.eq有一个参数的函数调用操作符const std::pair<std::string, unsigned>&, const std::pair<std::string, unsigned>&.由于类型不匹配,引用不能直接绑定到参数.但是,int可以隐式转换为unsigned,因此给定的对可以隐式转换为参数对.

因此,您隐式地为比较创建了一对临时参数.临时字符串的创建会导致内存分配.


如果您曾用作std::equal_to<>比较运算符,则它不会创建副本,因为它会推断出参数类型,因此不会导致转换.

  • 同样强制`key1`和`key2`的类型为`key_type`,通过指定类型而不是依赖于`auto`或通过添加使用`make_pair <key_type>`,将阻止额外的分配.(在第一种情况下,编译器足够聪明,可以在进行转换时移动字符串值). (2认同)