我正在试图弄清楚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(像素)的三元组:
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;
告诉我,我是否理解正确。
inputImage.data是一个字节数组,包括BGR值和每行末尾的偏移量;由于val是Matx的唯一数据成员,我们可以确信Vec3b是一组三个字节,因此当我依赖第10个指针时,我可以从第31个字节开始访问或修改三个字节。
只有两个问题:
1)为什么我们确定数据存储在内存中的方式?只是因为val是唯一的变量?
2)如果1.为真,你不认为这是一种危险的技术,因为只添加第二个变量会使几乎所有使用Vec2b的代码都无法使用吗?
答案 0 :(得分:1)
这通常会在实践中发挥作用,但存在一些潜在的缺陷。我们可以相对确定数据将如何在内存中布局,因为C ++非常具体地定义了从类定义到内存布局的映射。变量将按照它们在类定义中指定的顺序在内存中进行布局,尽管可以在变量之间插入填充以帮助对齐。由于两个项都是相同基类型的数组,因此我们可以确保每个元素的对齐方式相同。另外,指向第一个数据成员的指针通常等于指向对象本身的指针,尽管我认为只保证plain old data类型。在实践中,对于任何不涉及虚函数的事情都是如此。
这是危险的方法,正如你所提到的,矩阵或vec2b的成员变量的任何变化都会立即打破这一点。此外,添加任何虚拟方法都会破坏这一点,因为vtable将在对象的开头添加。