C++ 如何迭代通过引用传递的多个对象?

C++ 如何迭代通过引用传递的多个对象?,c++,iteration,pass-by-reference,C++,Iteration,Pass By Reference,假设我们有这个函数,其中vec1和vec2存储相同类型的数据: int myFunc(vector<int>& vec1, vector<int>& vec2) { for (auto const& elem : vec1) { // do something } for (auto const& elem : vec2) { // do the same thing } }

假设我们有这个函数,其中vec1和vec2存储相同类型的数据:

int myFunc(vector<int>& vec1, vector<int>& vec2) {
    for (auto const& elem : vec1) {
        // do something
    }
    for (auto const& elem : vec2) {
        // do the same thing
    }
}
int myFunc(向量和向量1,向量和向量2){
用于(自动常量和元素:vec1){
//做点什么
}
用于(自动常量和元素:vec2){
//做同样的事
}
}
显然,复制代码不是件好事。但是,以下不是解决方案:

int myFunc(vector<int>& vec1, vector<int>& vec2) {
    for (auto const& vec : {vec1, vec2}) {
        for (auto const& elem : vec) {
            // do something
        }
    }
}
int myFunc(向量和向量1,向量和向量2){
for(自动常量和向量:{vec1,vec2}){
用于(自动常量和元素:vec){
//做点什么
}
}
}
这样做会产生vec1和vec2的深层拷贝,这不是我们想要的。我看不到使用指针的方法,因为向量是通过引用传入的(假设我们不能更改函数签名)


那么,我们如何在不重复代码的情况下对vec1和vec2执行相同的操作呢?

一个解决方案是编写一个小lambda来“做一些事情”,然后您不必重复多次代码:

int myFunc(vector<int>& vec1, vector<int>& vec2) 
{
   auto do_something = [&](auto const & elem) {
        // do something
   }
 
   for (auto const& elem : vec1) {
        do_something(elem);
   }

   for (auto const& elem : vec2) {
        do_something(elem);    
   }
}
int myFunc(向量和向量1,向量和向量2)
{
自动执行某事=[&](自动常量和元素){
//做点什么
}
用于(自动常量和元素:vec1){
做点什么(元素);
}
用于(自动常量和元素:vec2){
做点什么(元素);
}
}

如果可以使用range-v3库,可以这样编写:

int myFunc(vector<int>& vec1, vector<int>& vec2) 
{
   for (auto const& elem : ranges::views::concat(vec1, vec2)) {
        // dosomething    
   }
}
int myFunc(向量和向量1,向量和向量2)
{
用于(自动常量和元素:范围::视图::concat(vec1,vec2)){
//剂量
}
}
它使用起来相当简单,可以避免制作深度拷贝,并且可以做与您最初想做的几乎相同的事情:

#include <iostream>
#include <functional>
#include <vector>

int myFunc(std::vector<int>& vec1, std::vector<int>& vec2) {
    for (auto const& vec : {std::ref(vec1), std::ref(vec2)}) {
        auto const &real_vec=vec.get();

        for (auto const& elem : real_vec) {
        }
    }
    return 0;
}

int main()
{
    std::vector<int> vec1, vec2;

    myFunc(vec1, vec2);
    return 0;
}
#包括
#包括
#包括
int myFunc(标准::向量和向量1,标准::向量和向量2){
for(auto const&vec:{std::ref(vec1),std::ref(vec2)}){
auto const&real_vec=vec.get();
用于(自动常量和元素:实际值){
}
}
返回0;
}
int main()
{
std::vec1,vec2;
myFunc(vec1,vec2);
返回0;
}

没有深度拷贝。

这里有许多不同的解决方案:

  • 迭代指针的
    std::initializer\u列表,或
    std::reference\u包装
    s

  • 编写一个lambda,包含循环体或整个循环。手动调用两次

  • 写入
    foreach_arg(lambda,args…)
    。使用它,传递在传入向量上循环的lambda

  • 将一个向量版本作为独立函数编写。叫它两次

  • 写一个可变版本。将循环放入lambda中并执行它

  • 将每个
    向量
    包装在
    std::span
    中,然后制作两个span的
    std::initializer\u列表
    ,然后进城

  • 编写一个ref数组类,将两个向量包装在其中,然后进城

  • 使用range-v3延迟连接向量并在连接过程中迭代


  • 我本来打算用一个函数,但我担心什么?你可以不用
    引用包装器
    做同样的事情,让外部数组保留
    向量*
    指针,例如:
    for(auto const*vec:{&vec1,&vec2}{auto const&real\u vec=*vec;}
    它们保证有相同数量的元素吗?如果是这样的话,一个索引循环就行了。不,它们不行。我以前从未听说过“逗号折叠执行”这个短语。我很喜欢:)