在C++中将子向量作为函数参数传递

5

给定一个大小为10的向量v1,我想将v1的第1、3和7个元素作为单个函数参数传递。除了创建另一个向量v2,并通过值复制三个元素并传递v2的引用之外,是否还有更有效的方法来传递参数(即不创建v2并按值复制元素)?


作为单个参数,我看不到解决方案。但是,您可以尝试可变参数函数。 - MichaelCMS
5个回答

3
根据所需的行为,您可以传递一个vector<reference_wrapper>或其他容器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]});
}

2
在这里使用std::reference_wrapper而不是指针有什么优势吗? - eerorika
@user2079303 的优点在于意图更清晰。在实现 f 方面,没有太大的区别;你可能需要使用 get() - 但也可能不需要,在这种情况下可以节省间接操作符。 - ecatmur

1

您说您不想创建一个新的向量并将所需元素复制到其中 - 那么考虑使用指向这3个元素的指针的新向量呢?或者一个指向这些元素的元组?

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

或者只是一个具有3个字段的自定义参数结构体-指向3个向量元素的指针?

或者是一个原始数组,其中包含指向3个向量元素的指针?(可能还需要一个额外的数组大小函数参数)

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

许多可能性,但我会选择使用带有副本的新向量,除非这样做过于昂贵,在这种情况下,指向原始向量的指针将是第二选择。创建向量真的不太可能成为性能问题。

1
你可以传递一个迭代器的向量:
#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});
}

0

你可以将索引与向量一起传递:

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


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

0
你可以插入一个转发函数来为你挑选出索引:
template <size_t... Is, typename F, typename C>
auto fwd_indices(F func, C& cont)
-> decltype(func(cont[Is]...))
{
    return func(cont[Is]...);
}

这是一种零拷贝、零额外对象的解决方案。您可以这样使用该函数:

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

如果你只知道运行时需要转发哪些索引,那么这是不可行的。但如果你在编译时就知道它们,那么这对我来说似乎非常干净。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接