2012-10-14 101 views
-1

我想弄清楚Vec3b如何为Opencv工作(但我认为它更多的是关于基本C++的问题)。
源代码如下(简化):了解如何在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是一组三个字节,所以当我考虑第10个指针时,我可以从第31个字节开始访问或修改三个字节。
只有两个问题:
1)为什么我们确信数据存储在内存中的方式?仅仅因为val是唯一的变量?
2)如果1.是真的,你不认为这是一种危险的技术,因为只添加第二个变量会使几乎所有使用Vec2b的代码不可用?

回答

1

这通常会在实践中发挥作用,但也有一些潜在的缺陷。我们可以相对确定数据如何在内存中进行布局,因为C++非常特别地定义了从类定义到内存映射的布局。变量将按照它们在类定义中指定的顺序排列在内存中,尽管可以在变量之间插入填充以帮助对齐。由于这两个项目都是相同基本类型的数组,我们可以确定每个元素的排列方式都是相同的。此外,指向第一个数据成员的指针通常会等于指向该对象本身的指针,但我认为这只适用于plain old data类型。在实践中,对于不涉及虚拟功能的任何事情都是如此。

这是危险的方法,正如你所说的矩阵或vec2b的成员变量的任何变化会立即打破这一点。另外,添加任何虚拟方法会破坏这个功能,因为vtable会在对象的开始处添加。

相关问题