我正在编写一些代码来集成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:因此它仍然很重要。
答案 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_ref
或std::string_view
)< / p>
答案 3 :(得分:0)
&#39;我可以使用指向原始数据的指针......只需将指针传递给x坐标即可。
你自己回答了你的问题。 std :: algorithms&s;什么都不做,否则。