【问题标题】:why would std::equal_to cause dynamic allocation?为什么 std::equal_to 会导致动态分配?
【发布时间】:2019-03-25 22:28:34
【问题描述】:

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

#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???
}

我看到的消息是

Allocating 31
Allocating 31
Finished initial allocations


Allocating 31
Allocating 31

比较key1key2 时,您可以看到发生了两个分配。但为什么? std::equal_to 的运算符通过 const 引用获取其参数,因此不应进行分配……我错过了什么?谢谢。

【问题讨论】:

  • 构建标志/编译器命令行?
  • @Yakk-AdamNevraumont gcc 8.2.0 使用 c++17 和 O2 优化

标签: c++ heap-memory std-pair


【解决方案1】:

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

keyX 的类型是std::pair&lt;std::string, int&gt;eq 具有参数const std::pair&lt;std::string, unsigned&gt;&amp;, const std::pair&lt;std::string, unsigned&gt;&amp; 的函数调用运算符。由于类型不匹配,引用不能直接绑定到参数。但是,int 可以隐式转换为 unsigned,因此给定的对可以隐式转换为参数对。

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


如果您使用std::equal_to&lt;&gt; 作为比较运算符,它不会创建副本,因为它会推断参数类型,因此不会导致转换。

【讨论】:

  • 同样强制key1key2的类型为key_type,或者通过指定类型而不是依赖auto或者通过使用make_pair&lt;key_type&gt;添加,将阻止额外分配。 (在第一种情况下,编译器足够聪明,可以在转换时移动字符串值)。
  • 作为一个 C++ 新手,我可能会尝试std::equal_to&lt;decltype(key1)&gt;,那会奏效吗?显然不如直接忽略它。
  • @pipe 确实也可以避免复制,因为在这种情况下,参数类型将与您的对的类型匹配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多