【问题标题】:Why does ranges-v3 not move elements even the iterator is std::move_iterator?为什么即使迭代器是 std::move_iterator,ranges-v3 也不移动元素?
【发布时间】:2020-08-08 10:48:02
【问题描述】:
#include <range/v3/all.hpp>
#include <vector>
#include <string>
#include <deque>

using namespace std::literals;

int main()
{
    auto src         = std::vector{"123"s, "456"s, "789"s};
    auto movable_rng = ranges::subrange(
                           std::make_move_iterator(src.begin()), 
                           std::make_move_iterator(src.end()));

    auto dst = ranges::to<std::deque<std::string>>(movable_rng);

    for (auto e : src)
    {
        std::cout << e << std::endl;
    }

    for (auto e : dst)
    {
        std::cout << e << std::endl;
    }
}

用clang 10用libc++编译,输出为:

123
456
789
123
456
789

如我所料,结果应该是:

""
""
""
123
456
789

为什么即使迭代器是 std::move_iterator,ranges-v3 也不移动元素?

======= 更新=======

我的范围版本是:range-v3-0.10.0。即使我将std::string 替换为std::vector&lt;char&gt;,问题在我的linux docker 上仍然可以重现,gcc 和clang 产生相同的结果。

但是,godbolt.org 上的相同代码是可以的,但我不确定godbold.org 上的范围版本是 3.0.10

【问题讨论】:

  • 实际上,我得到了预期的result
  • 我的编译器是 clang 10 而不是 gcc。
  • clang 显示相同的 thing
  • 没有要求移动的字符串必须为空。
  • 由于移动的元素只需要处于“有效但未指定的状态”,因此您没有证据表明移动没有发生。您也许可以编写自己的类来记录它何时被移动以更好地说明正在发生的事情。

标签: c++ standards move-semantics rvalue-reference range-v3


【解决方案1】:

cppreference 上的示例代码是这样的:

std::string str1;
std::string str2 { "alpha" };
...
str1 = std::move(str2);
std::cout << std::quoted(str1) << ' ' // "alpha"
          << std::quoted(str2) << '\n'; // "" or "alpha" (unspecified)

可能由于小的字符串优化,不要求移出的字符串为空。允许在移动后保持不变。唯一的要求是它仍然处于有效状态。

【讨论】:

    【解决方案2】:

    从一个对象移动会使其处于有效但未定义的状态。由于您的字符串都很小,因此很有可能所有字符都存储在对象内部而不是堆中(SSO)。这使得在“移动”之后将被移动的字符串归零的效率较低(略微)。

    【讨论】:

      猜你喜欢
      • 2021-08-21
      • 2020-01-11
      • 1970-01-01
      • 2021-05-11
      • 2015-05-15
      • 2020-07-23
      • 2018-10-21
      • 1970-01-01
      • 2016-04-16
      相关资源
      最近更新 更多