私はいくつかの 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 から始まる座標を部分分解しています。私たちが何をしているのかを理解するには、常に二重のテイクが必要です。もちろん、これは行列では最悪です。
明らかな解決策の 1 つは、わずかに異なるオーバーロードです。
double& Vector::operator[](int i) {
return coordinates[i-1] ;
}
入力できるように
double x1 = V[1];
V[2] = coord2;
この i-1 減算は、小さなオーバーヘッドの良い候補と思われます。非常に小さいと言うかもしれませんが、私は計算力学を行っているため、通常、これは余裕のないものです。
だから今(最後に)私の質問:コンパイラはこれを最適化できると思いますか、それとも最適化する方法はありますか?(テンプレート、マクロ、ポインター、または参照クラッジ...)
論理的には、
double xi = V[i];
ほとんどの場合、ブラケット間の整数はリテラルです (ループの 3 回反復を除く)。
(この長い質問で申し訳ありません)
編集:
すべてのコメントと回答に感謝します
インデックスが 0 のベクトルに慣れているという人々の意見には同意しません。オブジェクト指向の観点からは、0 インデックスの配列で実装されているため、数学 Vector を 0 インデックスにする理由はないと思います。基礎となる実装を気にする必要はないと思われます。ここで、パフォーマンスを気にせず、マップを使用して Vector クラスを実装するとします。次に、「1」を「1番目」の座標にマッピングするのが自然だと思います。
とは言っても、私は 1 インデックスのベクトルと行列を試してみましたが、いくつかのコードを書いた後、配列を使用するたびにうまく相互作用しないことがわかりました。Vector とコンテナー (std::array、std::vector...) は頻繁に対話することはないと思いますが (相互にデータを転送することを意味します)、それは間違っていたようです。
今、私はあまり物議を醸していないと思う解決策を持っています(あなたの意見を教えてください):物理的なコンテキストでベクターを使用するたびに、列挙型を使用することを考えます:
enum Coord {
x = 0,
y = 1,
z = 2
};
Vector V;
V[x] = 1;
私が見る唯一の欠点は、これらの x、y、および z が警告なしで再定義できることです...