我正在做一些 C++ 计算力学(别担心,这里不需要物理知识),有些事情真的让我很困扰。
假设我想表示一个 3D 数学向量(与 std::vector 无关):
class Vector {
public:
Vector(double x=0., double y=0., double z=0.) {
coordinates[0] = x;
coordinates[1] = y;
coordinates[2] = z;
}
private:
double coordinates[3];
};
到目前为止,一切都很好。现在我可以重载 operator[] 来提取坐标:
double& Vector::operator[](int i) {
return coordinates[i] ;
}
所以我可以输入:
Vector V;
… //complex computation with V
double x1 = V[0];
V[1] = coord2;
问题是,从 0 开始索引在这里并不自然。我的意思是,在对数组进行排序时,我不介意,但事实是,每篇论文、书籍或任何东西中的常规符号总是以 1 开头的坐标。这似乎是一个小问题,但事实是在公式中,它总是需要仔细考虑才能理解我们正在做什么。当然,这对于矩阵来说是最糟糕的。
一个明显的解决方案是稍微不同的重载:
double& Vector::operator[](int i) {
return coordinates[i-1] ;
}
所以我可以输入
double x1 = V[1];
V[2] = coord2;
除了一件事之外,它似乎很完美:这个 i-1 减法似乎是一个小开销的好候选。你会说很小,但我正在做计算力学,所以这通常是我们负担不起的。
所以现在(最后)我的问题:你认为编译器可以优化这个,还是有办法让它优化?(模板、宏、指针或参考组合...)
逻辑上,在
double xi = V[i];
括号之间的整数大部分时间都是文字(除了在 3 次迭代 for 循环中),内联 operator[] 应该使它成为可能,对吧?
(对不起这个冗长的问题)
编辑:
感谢您的所有评论和回答
我有点不同意人们告诉我我们习惯于 0-indexed 向量。从面向对象的角度来看,我认为没有理由将数学向量设为 0 索引,因为它是使用 0 索引数组实现的。我们不应该关心底层实现。现在,假设我不关心性能并使用映射来实现 Vector 类。然后我会发现将'1'与'1st'坐标映射是很自然的。
也就是说,我尝试了 1-indexed 向量和矩阵,并且在编写了一些代码之后,我发现每次使用数组时它都不能很好地交互。我认为 Vector 和容器 (std::array,std::vector...) 不会经常交互(意思是在彼此之间传输数据),但似乎我错了。
现在我有一个我认为争议较小的解决方案(请给我你的意见):每次我在某些物理环境中使用 Vector 时,我都会考虑使用 enum :
enum Coord {
x = 0,
y = 1,
z = 2
};
Vector V;
V[x] = 1;
我看到的唯一缺点是这些 x、y 和 z 可以在没有警告的情况下重新定义......