-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 是一组三个字节,因此当我遵循第 10 个指针时,我可以访问或修改从第 31 个字节开始的三个字节。
只有两个问题:
1)为什么我们确定数据在内存中的存储方式?仅仅因为 val 是唯一的变量?
2) 如果 1. 为真,您不认为这是一种危险的技术吗,因为仅添加第二个变量会使几乎所有使用 Vec2b 的代码都无法使用?

4

1 回答 1

1

这通常会在实践中起作用,但存在一些潜在的陷阱。我们可以相对确定数据在内存中的布局方式,因为 C++ 相当明确地定义了从类定义到内存布局的映射。变量将按照它们在类定义中指定的顺序排列在内存中,尽管可以在变量之间插入填充以帮助对齐。由于这两个项目都是相同基本类型的数组,我们可以确保每个元素的对齐方式相同。此外,指向第一个数据成员的指针通常等于指向对象本身的指针,尽管我认为这仅适用于普通的旧数据类型。在实践中,这对于任何不涉及虚函数的东西都是正确的。

这是危险的方式,因为您提到矩阵或 vec2b 的成员变量的任何更改都会立即破坏这一点。此外,添加任何虚拟方法都会破坏这一点,因为 vtable 将添加到对象的开头。

于 2012-10-14T08:21:19.933 回答