用于包含不同元素的 2 个向量的单个迭代器 (c++)

Single iterator for 2 vectors holding different elements (c++)

我有两个相同长度的向量。其中之一包含 double 向量:

std::vector<std::vector<double>> A;

第二个持有双打

std::vector<double> B;

我所说的“相同长度”是指 A 包含的双精度向量与 B 包含的双精度向量一样多。 我想同时用一个迭代器遍历它们。我觉得我需要创建一个 class 来做到这一点。像

std::vector<vector<double>>::iterator iter = A.begin();
for (A= iter.begin(); iter != A.end(); iter++)
{
 (*iter).A // I access an element of A std::vector<double>
 (*iter).B // I access an element of B (double)
}

我检查了一个类似的问题,这个问题非常接近我想做的: 但在我的例子中,迭代器有两种不同的类型,分别是std::vector<vector<double>>::iteratorvector<double>::iterator,所以这个问题的解决方案不起作用,但我想它很接近。

我该怎么做?什么是最好的方法?

原则上,您可以编写一个自定义迭代器,它有一个 first 和一个 second,分别引用 AB 的元素。然而,自定义迭代器并不简单。更简单的替代方法是使用基于循环的普通旧索引:

for (size_t i = 0; i < A.size() && i < B.size(); ++i)
{
     A[i]; // I access an element of A std::vector<double>
     B[i]; // I access an element of B (double)
}

或者使用两个迭代器

auto itA = A.begin();
auto itB = B.begin();
for ( ; itA != A.end() && itB != B.end(); ++itA,++itB) {
    //...
}

您可能还对来自 boost 的 zip_iterator 或来自 ranges-v3 库的 view::zip 感兴趣:

#include <iostream>
#include <vector>
#include <range/v3/view.hpp>    

int main() {
    std::vector<int> A{1,2,3,4,5};
    std::vector<double> B{1.2,3.4,5.6,7.8,9.1};
    for (const auto& [a, b] : ranges::view::zip(A, B)) { 
        std::cout << a << "  " << b << "\n";
    }
}

Live Demo

标准范围库基于 Nieblers 范围,但到目前为止 zip 还没有进入标准库。如果我理解正确的话,这是 C++23 的预期。


PS:请注意,您的 for (A= iter.begin(); iter != A.end(); iter++) 可以被认为是“老式的”。由于 C++11 有 range based for loops,它允许您从开始到结束迭代容器的元素。他们更进一步,还向您隐藏了迭代器(它们仍然存在),以减少打字错误的机会。虽然,就像基于迭代器的循环比基于索引的循环稍微不灵活一样,基于范围的循环比基于迭代器的循环更不灵活。他们只让你从 begin 迭代到 end:

for (const auto& a : A) { 
    a; // a is a const reference to element in A
}

为了完整起见,我只是提到这一点,与旧的基于迭代器的循环相比,基于范围的循环将两个迭代器“压缩”为一个既不简单也不复杂。