简体   繁体   中英

Passing sub-vector as function argument in c++

Given a vector v1 of size 10, I want to pass the 1st, 3rd and 7th element of v1 as a single function argument. Instead of creating another vector v2, copying the three elements from v1 by value and passing the reference of v2, is there any more efficient way to pass the argument (ie without creating v2 and copying elements by value)?

Depending on desired behavior, you can pass a vector<reference_wrapper> or other container of reference_wrapper :

#include <vector>
#include <functional>

void f(std::vector<std::reference_wrapper<double>>) {}
void g() {
  std::vector<double> v(10);
  f({v[0], v[2], v[6]});
}

You say you don't want to create a new vector and copy the needed elements to it - what about a new vector with pointers to the 3 elements? Or a tuple with pointers to the elements?

std::vector<Element> items { e0, e1, e2, e3, e4, e5, e6, e7 };
auto tuple = std::make_tuple(&items[0], &items[2], &items[6]);

Or just a custom parameter struct with 3 fields - pointers to the 3 vector elements?

Or a raw array with pointers to the 3 vector elements? (Maybe with an additional array size function parameter)

std::vector<Element> items { e0, e1, e2, e3, e4, e5, e6, e7 };
Element subItems[3] { &items[0], &items[2], &items[6] };

Many possibilities, but I'd go for a new vector with copies, unless that is unnecessarily expensive, in which case pointers to the original would be a second choice. Creating the vector is really unlikely to be a perf problem.

You could pass the indices alongside with the vector:

std::vector<unsigned> indices = { 1, 3, 5 };


void f(const std::vector<int>& X, const std::vector<unsigned>& idx)
{
    // Do something
}

You could insert a forwarding function to pick out the indices for you:

template <size_t... Is, typename F, typename C>
auto fwd_indices(F func, C& cont)
-> decltype(func(cont[Is]...))
{
    return func(cont[Is]...);
}

This is a zero-copy, zero-extra-object solution. You can use that function thusly:

std::vector<int> v = { .. };
fwd_indices<0, 2, 6>(some_func, v); // calls some_func(v[0], v[2], v[6]);
                                    // which hopefully takes them by-ref

If you only know what indices you need to forward at run-time, this is a nogo. But if you know them at compile time, this seems pretty clean to me.

You could pass a vector of iterators:

#include <vector>
#include <iostream>

using itr_type = std::vector<double>::const_iterator;

void doSomethingWithItrVec(std::vector<itr_type> itr_vec) {
  for (auto itr : itr_vec)
    std::cout << *itr << "\n";
}

int main() {
    std::vector<double> v = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0};
    auto begin = v.cbegin();
    doSomethingWithItrVec({begin, begin + 2, begin + 6});
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM