好吧,我\xe2\x80\x99m 对将 Mat 传递给函数并检索它有点困惑\n所以我们可以说两者之间有什么区别
\n\n void GetFrame(Mat& frame)\n Vs \n void GetFrame(Mat frame) \n Vs \n Mat GetFrame()\nRun Code Online (Sandbox Code Playgroud)\n\n更新:
\n\n在哪个版本中,函数体内框架的更改将导致传递给函数的原始框架发生更改
\n只要稍加小心,您就可以让所有 3 个版本都正常工作并执行相同的操作,但我会尝试解释详细信息。
首先,Mat对象实际上只是一个小标头,其中包含有关实际数据的元数据(例如,行数和列数)以及指向实际数据的指针。在大多数情况下,该指针实际上是一个智能指针,具有引用计数,并且可以被多个Mat对象共享,并且当最后一个剩余Mat对象停止指向它时自动删除。(Mat对象也可以指向它不拥有的数据,即如果您有从不同的库/API 获得的一些数据,并且想要重用相同的内存而不是复制它。)
您的函数的版本 1 可能是最简单的。调用者的Mat对象是通过引用复制的,这显然意味着对Mat对象元数据(包括(智能)指针)的任何修改在返回时将对调用者可见。底层数据显然会反映函数所做的任何修改。
在函数的版本 2 中(Mat按值传递对象), 表示的小标头Mat被复制并传递给函数。复制是浅的:元数据和(智能)指针被复制,但底层数据由调用者的Mat对象和被调用者的Mat对象共享。需要注意的是,如果函数修改了复制frame对象的元数据,这些更改对于调用者来说是不可见的。
例如,如果您传递一个空的Mat,您可能会对结果感到惊讶:首先,空的元数据Mat被复制。当函数调用类似 的函数时frame.create(newRows, newCols, newType);,该create函数将分配一个新的内存块,因为frame.rows != newRows、frame.cols != newCols、 和frame.type() != newType,并且元数据(仅被调用者的副本)frame更新以反映新分配的数据。当函数返回时,其frame对象将保存对智能指针的唯一引用,因此数据将被自动丢弃。调用者仍然只有一个空标头。
但是,如果Mat传递给函数的对象已经具有正确的维度和类型,frame.create()则不会执行任何操作,这意味着被调用者对基础数据所做的任何修改将对调用者可见。
第三个版本与第二个版本类似,不同之处在于,函数不是在调用函数时复制元数据,而是分配一个Mat它认为合适的元数据(包括指向底层数据的指针)返回时被复制回调用者。底层数据仍然存在并且可供调用者访问。
如果您事先不知道数据的大小和类型,则无法使用按值传递。如果您确实知道大小/类型,则可以使用按值传递,并且将使用预先分配的内存。
如果可能的话,按引用传递将使用预先分配的内存,或者分配新的内存,在任何一种情况下,调用者都将始终看到新的标头/数据。
按值返回也将始终正常工作,但它确实必须在每次调用时重新分配新内存,这可能是不可取的。