【问题标题】:Only Move Iterator Once只移动一次迭代器
【发布时间】:2016-05-19 12:59:11
【问题描述】:

我正在努力寻找改进my answer here 的方法。让我们将问题简化为:我想将输入容器划分为 vectorvectors,大小为 STEP,最后一个 vectors 应该有一个较小的如果输入容器中剩余的元素少于STEP,则我们称这个分区容器为bar

我不想多次迭代我的输入或输出范围。我要解决的问题的要素很简单:

  1. 附加bar 构造vector,大小为min(STEP, distance(it, foo.end())
  2. 在构造容器后让it 指向advance(it, size(bar.back()))
  3. 就地执行vector 构建

我对这个问题的回答的翻译是:

auto it = cbegin(foo);

for (auto i = size(foo); i > STEP; i -= STEP) {
    bar.push_back(decltype(bar)::value_type(STEP));
    for (auto internalIt = bar.back().begin(); internalIt != bar.back().end(); ++internalIt, ++it) {
        *internalIt = *it;
    }
}
bar.push_back(decltype(bar)::value_type(it, cend(foo)));

问题出在这一行:bar.push_back(decltype(bar)::value_type(STEP)) 我正在分配vector 并将其组件初始化为0。有没有更好的方法来做到这一点,在这种方法下我仍然只会遍历输入和输出范围一次?

【问题讨论】:

    标签: c++ vector iterator initialization iteration


    【解决方案1】:
    bar.push_back(decltype(bar)::value_type{}); // or bar.resize(bar.size() + 1); if you prefer
    bar.back().reserve(STEP);
    while (bar.back().size() < STEP) {
        bar.back().push_back(*it);
        ++it;
    }
    

    std::copy_n 返回高级 output 迭代器真是倒霉,而你需要保留的是高级 input 迭代器,否则你可以使用它代替循环(使用std::back_inserter 获取目标迭代器)。

    如果您担心bar.back().size() 的性能,请随意使用计数器变量!

    【讨论】:

    • 大声笑,我的代码中实际上有copy_n,直到我查看它并意识到它按值获取迭代器之前,我无法弄清楚为什么我的输入迭代器没有变得先进。无论如何,您的意思是,空构造、空间分配和back_inserter 比分配空间和直接分配的构造更好?
    • 好的,所以我已经对其进行了基准测试,并且可以确认构造、分配和插入总是比使用分配和分配的构造慢:coliru.stacked-crooked.com/a/206b8278ff67817f 顺便说一句,我不知道发生了什么使用 Coliru,但我不相信它的结果,因为它们总是以 10,000 为增量。但如果你复制这个并在本地运行,你可以确认我的评估。
    • @JonathanMee:它只是在您要求的意义上“更好”,它只在结果向量bar 的每个子向量上运行一次,而您的代码在它上面运行两次(一次零初始化和一次分配)。我什至没有考虑它在任何特定的vector 实现上是否具有更好或更差的运行时间,我对bar.back().size() 性能的评论只是事后的想法。有了足够大的内存缓存,缓存未命中的成本确实很高,而且STEP 足以破坏缓存,我们可以安排它比您的代码运行得更快;-)
    • 您的意思是,如果分配的向量大到足以导致缓存未命中,我的代码会更昂贵,因为它必须遍历,0 初始化值,然后它必须遍历赋值?我认为情况并非如此。编译器足够聪明,知道我正在执行calloc 并请求0 初始化内存:stackoverflow.com/a/2688522/2642059
    • @JonathanMee:取决于value_type,它可能不是一个calloc(因为它实际上可能不是零初始化,尽管我已经这么称呼它了)。但足够公平。
    猜你喜欢
    • 2017-07-05
    • 2015-03-29
    • 2021-02-26
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    • 2016-02-01
    • 2012-05-28
    • 1970-01-01
    相关资源
    最近更新 更多