C ++:std :: vector - 可以“切片”一个向量吗?

时间:2015-06-08 19:57:06

标签: c++ c++11 vector slice array-view

我正在编写一些代码来集成ODE。这个问题同样是对解决方案的编码建议的要求,所以如果您对我即将提供的建议有其他建议,请告诉我!

由ODE集成商集成的“对象”以6个“块”形式出现......原因是我有一个std :: vector of double,它们按以下方式排列:< / p>

前3个双打是位置坐标; x,y和z。 接下来的3个双打是速度坐标; x,y和z。

所以,现在你知道了,我有一个函数,它将成对的“position”“”“vectors”“”作为参数并返回某种结果......看看我在哪里跟着这个?

目前,该功能需要以下列方式使用2个位置坐标:

std::vector<double> magic_gravity_formula(const std::vector<double> &r1,
          const std::vector<double> &r2, const double m1, const double m2)

我不想将3组中的所有数据复制到新的向量 - 这是一种疯狂(并且非常慢)的编程方式。

可以使用指向原始数据的指针......并且只是将指针传递给x坐标(3个双打块中的第一个项目) - 这对我来说似乎没什么好看但是也许有更好的方法?有点像Python或Matlab数组切片?我可以这样做吗?

我想传递一个新的向量(或某种类型的包装类?),它是从已经存储在数组中的数据创建的......有点像

std::vector<double> sub_section_of_data = data[0..2] // Obviously pseudocode!

好的,所以上面的内容是荒谬的,因为大概是一种实现了这种语法的语言仍会进行复制操作,这可能很慢 - 正是我想要避免的......

所以是的,我不确定这里最好的方法 - 有人能建议一个“好”的解决方案吗? (以非主观的方式!)

编辑:为了使这一点非常清楚 - 问题是我不想做类似的事情:

std::vector<double> r1_temp;
r1_temp.push_back(data[0]); // Copy ! Bad !
r1_temp.push_back(data[1]);
r1_temp.push_back(data[2]);

... same for an r2 ...

std::vector<double> force = magic_gravity_formula(r1, r2, m1, m2);

编辑2:考虑编译器选项 - 编译器是否可以通过以下方式更改函数以接受参数来优化我的代码:

std::vector<double> super_gravity_formula(double x1, double y1, double z1, double x2, double y2, double z2, double m1, double m2)

在这种情况下,或许这个问题并不重要? (除了形成“使你的代码看起来很好看”的观点之外。)

编辑3:因此它仍然很重要。

4 个答案:

答案 0 :(得分:6)

您想要查看现有的矢量。

std::experimental::array_view<T>,或推出自己的。

数组视图是一对T*和访问器,可让您将其视为数组operator[] .begin() .back() size() {{ 1}}等等。

Here is one of many such implementations I've rolled。那个有点重,有一个empty()视图可以自适应地处理随机访问迭代器,一个range<Iterator>继承自array_view<T>

如果它不起作用,请在“yakk”上用“array_view”搜索SO上的其他帖子,或者自己调试。我已经写了至少六次,或多或少的调试,具有不同的range<T*>正确性规则。

一旦拥有它,const将构建一个{ vec.data()+index, vec.data()+index+3 },其开销几乎为零。

答案 1 :(得分:1)

如果你想要的是向量,在数学意义上,对于6个double类型的元素,std::vector<double>可能不是最有效的表示。我会继续定义一个3D点,然后将位置+速度定义为:

struct point {
   double x, y, z;
};
struct position_and_velocity {
   point pos;
   point vel;
};

对这些类型进行操作可能比在向量上操作(没有动态分配)更有效,并且您可以将其作为进行操作。这个结构的整个副本可能比将第一个元素插入std::vector要便宜,而且比提供两个指向数组以获得 slice 的点慢一点但不多。

此外,它不会出错,因为在切片数组的情况下,您可能会错误地使用错误的值并最终得到类似(伪代码)slice[1..3]的内容是两个位置坐标与一个速度坐标(可能是非感性的)。

函数签名是程序二进制接口的一部分,除非内联代码,否则编译器不会更改函数签名。此外,我非常怀疑编译器会删除任何转换中向量固有的动态分配(除非它可以删除整个变量)。

答案 2 :(得分:0)

由于代码需要const std::vector<double> &,因此您无法变得更聪明。

否则(如果库函数更通用)你可以很容易地传递一个范围(参见例如Boost Range,但你可以轻松地一次性矢量子范围,就像boost::string_refstd::string_view)< / p>

答案 3 :(得分:0)

&#39;我可以使用指向原始数据的指针......只需将指针传递给x坐标即可。

你自己回答了你的问题。 std :: algorithms&s;什么都不做,否则。