-1

私はVec3bがOpencvでどのように機能するかを理解しようとしています(しかし、それは基本的なc ++についての質問だと思います)。
ソースコードは次のとおりです(簡略化)。

template<typename _Tp, int m, int n> class CV_EXPORTS Matx
{
    public:
    // constructors, methods and operators
    ...
        _Tp val[m*n]; //< matrix elements
};


// inherits from Matx
template<typename _Tp, int cn> class CV_EXPORTS Vec : public Matx<_Tp, cn, 1>
{
    public:
    // constructors, methods and operators
    ...
};

typedef Vec<uchar, 3> Vec3b; 

たとえば、画像からBGR(ピクセル)のトリプレットを読み取るために使用できます。

int main( int argc, char** argv )
{
    Vec3b* data= (Vec3b*)inputImage.data;
    // access the 10th pixel
    data[10] = Vec3b(0,0,255);
}

正しく理解できたか教えてください。
inputImage.dataは、各行の終わりにあるBGR値とオフセットで構成されるバイトの配列です。valはMatxの唯一のデータメンバーであるため、Vec3bは3バイトのセットであることが保証されます。したがって、10番目のポインターを参照すると、31バイトから3バイトにアクセスまたは変更できます。
たった2つの質問:
1)データがメモリに保存される方法について確信があるのはなぜですか?valが唯一の変数だからだけ?
2)1.が真の場合、2番目の変数を追加するだけで、Vec2bを使用するほとんどすべてのコードが使用できなくなるため、危険な手法だと思いませんか?

4

1 に答える 1

1

これは通常実際には機能しますが、いくつかの潜在的な落とし穴があります。C ++はクラス定義からメモリレイアウトへのマッピングをかなり具体的に定義しているため、データがメモリ内でどのようにレイアウトされるかについては比較的確信が持てます。変数は、クラス定義で指定されているのと同じ順序でメモリに配置されますが、変数の間にパディングを挿入して位置合わせを支援することができます。両方のアイテムは同じ基本タイプの配列であるため、各要素が同じように配置されていることを確認できます。さらに、最初のデータメンバーへのポインターは通常、オブジェクト自体へのポインターと同じですが、これは単純な古いデータ型に対してのみ保証されていると思います。実際には、これは仮想関数を含まないものすべてに当てはまります。

これが危険な方法は、matrixまたはvec2bのメンバー変数の変更があれば、すぐにこれを壊してしまうことです。さらに、仮想メソッドを追加すると、オブジェクトの先頭にvtableが追加されるため、これが機能しなくなります。

于 2012-10-14T08:21:19.933 に答える