【问题标题】:Will structure like std::list<std::pair<string, string>> be copied when returned?像 std::list<std::pair<string, string>> 这样的结构会在返回时被复制吗?
【发布时间】:2020-09-21 19:07:06
【问题描述】:

我有一个函数可以从给定的字符串中提取键值列表,其中每个键/值对都由std::pair 表示,该函数具有如下签名:

std::list<std::pair<string, string>> extract(const string &s)

如果我的实现如下所示:

list<pair<...>> kv_pairs;
for (....) {
  kv_pairs.push_back(make_pair(k, v));
}
return kv_pairs;

1) 我不希望发生任何复制,我想知道 RVO/NRVO 是否会应用于列表中的对和保存它们的列表。

2) 如果在这种情况下会发生复制,那么在不复制的情况下实现这一点的替代数据结构是什么?我可以想到一个使用unique_ptr&lt;unorder_map&lt;&gt;&gt; 的解决方案,但就我而言,我只需要支持列表中对的迭代,不需要支持通过它们的键查找值,所以我想避免不必要的哈希计算在插入过程中。

3) 我知道 RVO/NRVO 是依赖于编译器的行为,有什么方法可以验证这些行为是否容易发生?

【问题讨论】:

  • 从 C++17 RVO 开始是强制性的,并且依赖于编译器:en.cppreference.com/w/cpp/language/copy_elision 您也可以随时进行老式的传递引用。
  • 不要忘记移动列表,如果没有复制省略就可以做到。
  • ^ 那。从 C++11 开始,即使没有 RVO,列表也会被移动构造。列表的移动基本上只是传输两个指针(头和尾),也许还有一些元数据(大小)。
  • 和往常一样,始终首先以简单直接的方式进行操作。如果以任何方式存在性能问题,那么您测量、基准测试和分析(优化的构建)以找到前两个或三个瓶颈并修复这些瓶颈,并提供大量关于它的文档(例如为什么要这样做) )。

标签: c++ list std-pair rvo nrvo


【解决方案1】:

如果您至少针对 C++11 进行编译,则实际上只有两种可能的结果:

  • 如果没有 RVO,返回的临时值将用于移动构造分配返回值的对象。这基本上只是在移动几个指针,无论列表中有多少项,都将花费完全相同的时间(可以忽略不计)。
  • 使用 RVO,可以省略移动构造。

两种结果都非常快,不会涉及复制列表结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-01
    • 2011-06-06
    • 1970-01-01
    • 2011-03-26
    • 2011-10-29
    • 1970-01-01
    • 2014-12-22
    • 2012-12-12
    相关资源
    最近更新 更多