简体   繁体   English

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

[英]C++: std::vector - It is possible to “slice” a vector?

I am writing some code to integrate ODE's. 我正在编写一些代码来集成ODE。 This question is as much a request for coding advice as for a solution, so if you have an alternative suggestion to the one I am about to offer please let me know! 这个问题同样是对解决方案的编码建议的要求,所以如果您对我即将提供的建议有其他建议,请告诉我!

The "objects" to be integrated by the ODE integrator come in "blocks" of 6... The reason for this is that I have a std::vector of doubles, and they are arranged in the following way: 由ODE集成商集成的“对象”以6个“块”为单位......原因是我有一个std :: vector of double,它们按以下方式排列:

The first 3 doubles are position coordinates; 前3个双打是位置坐标; x, y and z. x,y和z。 The next 3 doubles are velocity coordinates; 接下来的3个双打是速度坐标; x, y and z. x,y和z。

So, now you know that, I have a function which takes pairs of "position" """vectors""" as arguments and returns some sort of result... See where I'm going with this? 所以,现在你知道了,我有一个函数,它将成对的“位置” “”“向量”“”作为参数并返回某种结果...看看我要去哪里?

Currently the function expects 2 lots of position coordinates in the following manner: 目前,该函数需要以下列方式使用2个位置坐标:

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

I don't want to copy all the data in group of 3 to new vectors - that's a crazy (and very slow) way to program something. 我不想将3组中的所有数据复制到新的向量 - 这是一种疯狂(并且非常慢)的编程方式。

I could use pointers to the raw data instead... and just pass a pointer to the x coordinate (first item in a block of 3 doubles) - this seems kind of okay to me but perhaps there's a better method? 可以使用指向原始数据的指针......并且只是将指针传递给x坐标(3个双打块中的第一个项目) - 这对我来说似乎没有问题,但也许有更好的方法? Kind of something like Python or Matlab array slicing? 有点像Python或Matlab数组切片? Can I do something like that? 我可以这样做吗?

I kind of want to pass a new vector (or some sort of wrapper class?), created from the data already stored in the array... Something kind of like 我想传递一个新的向量(或某种包装类?),从已经存储在数组中的数据创建...有点像

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

Okay so the above is nonsensical, because presumably a language which implemented that syntax would still make a copy operation, which is likely to be slow - exactly what I am trying to avoid... 好的,所以上面的内容是荒谬的,因为大概是一种实现了这种语法的语言仍然可以进行复制操作,这可能很慢 - 正是我想要避免的......

So yeah I am not sure exactly the best way to proceed here - can anyone suggest a "good" solution? 所以,是的,我不确定这里最好的方式 - 有人能建议一个“好”的解决方案吗? (In the non-subjective way!) (以非主观的方式!)

EDIT: To make this really clear - the problem is I don't want to do something like: 编辑:为了使这一点非常清楚 - 问题是我不想做类似的事情:

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);

EDIT 2: Consider compiler options - would the compiler optimize my code for me by doing something like changing the function to accept arguments in the following way: 编辑2:考虑编译器选项 - 编译器是否会通过执行诸如更改函数以接受参数的方式为我优化我的代码:

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

In which case, perhaps this question isn't important? 在这种情况下,也许这个问题并不重要? (Other than form a "make your code look nice to read" point of view.) (除了形成“使你的代码看起来很好看”的观点。)

Edit 3: Therefore it is still important. 编辑3:因此它仍然很重要。

You want a view into an existing vector. 您想要查看现有的矢量。

std::experimental::array_view<T> , or roll your own. std::experimental::array_view<T> ,或者滚动你自己的。

An array view is a pair of T* , and accessors that let you treat it sort of like an array operator[] .begin() .back() size() empty() etc. 数组视图是一对T*和访问器,可以让它像数组operator[]一样处理operator[] .begin() .back() size() empty()等。

Here is one of many such implementations I've rolled . 这是我推出的许多此类实现之一 That one is a bit heavy weight, with a range<Iterator> view that adaptively handles random access iterators, and an array_view<T> that inherits from range<T*> . 那个有点重,有一个range<Iterator>视图,自适应地处理随机访问迭代器,以及一个继承自range<T*>array_view<T> range<T*>

If it doesn't work, search for another post on SO by "yakk" with the word "array_view" or debug it yourself. 如果它不起作用,请在“yakk”上用“array_view”搜索SO上的其他帖子,或者自己调试。 I've written it at least a half dozen times, with more or less debugging, with different const correctness rules. 我已经写了至少六次,或多或少的调试,具有不同的const正确性规则。

Once you have it, { vec.data()+index, vec.data()+index+3 } will construct an array_view<double> with next to zero overhead. 一旦你拥有它, { vec.data()+index, vec.data()+index+3 }将构造一个array_view<double> ,其开销接近零。

If what you want is vectors , in the math sense, of 6 elements of type double, std::vector<double> might not be the most efficient representation. 如果你想要的是矢量 ,在数学意义上,6个double类型的元素, std::vector<double>可能不是最有效的表示。 I would just go ahead and define a 3D point and then the position + velocity as: 我会继续定义一个3D点然后位置+速度为:

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

Operating on this types will probably be more efficient than operating on vectors (no dynamic allocations), and you could just operate on this as values . 对这些类型进行操作可能比在向量上操作(没有动态分配)更有效,并且您可以将其作为值进行操作 A whole copy of this structure is probably cheaper than inserting the first element into the std::vector , and a bit slower but not much than providing two pointers into an array to get a slice . 这个结构的整个副本可能比将第一个元素插入std::vector更便宜,并且比提供两个指向数组以获得切片的指针要慢一些但不多。

Additionally it will be less error prone, as in the case of slicing an array you could by mistake use the wrong values and end up with things like (pseudo code) slice[1..3] that is two of the position coordinates with one of the velocity coordinates (probably non-sensical). 此外,它会减少错误,因为在切片数组的情况下你可能会错误地使用错误的值并最终得到像(伪代码) slice[1..3]那样的位置坐标的两个位置坐标速度坐标(可能是非感性的)。

The function signature is part of the binary interface of your program, a compiler will not change the function signature unless it inlines the code. 函数签名是程序二进制接口的一部分,除非内联代码,否则编译器不会更改函数签名。 Furthermore, I would very much doubt that a compiler would remove the dynamic allocation inherent to vectors in any of the transformations (unless it can remove the whole variable). 此外,我非常怀疑编译器会删除任何转换中向量固有的动态分配(除非它可以删除整个变量)。

Since the code requires const std::vector<double> & you cannot be smarter. 由于代码需要const std::vector<double> &你不能更聪明。

Otherwise (if the library functions were more generic) you could easily pass a range (see eg Boost Range, but you could easily one-off a vector subrange much like boost::string_ref or std::string_view ) 否则(如果库函数更通用)你可以很容易地传递一个范围(参见例如Boost Range,但你可以轻松地一次性一个向std::string_view范围,就像boost::string_refstd::string_view

'I could use pointers to the raw data instead... and just pass a pointer to the x coordinate'. '我可以使用指向原始数据的指针......只需将指针传递给x坐标'。

You answered your question, yourself. 你自己回答了你的问题。 std::algorithms's do nothing, else. std :: algorithms's什么都不做,否则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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