cv::UMat
毫无疑问是);
但是,我尝试使用返回类型的函数嵌套是否仍然有效?是否仍然会出现复制省略,并达到预期的结果?
我目前正在使用OpenCV' cv::UMat
对象类,我的同事写了一个函数来添加cv::UMat
如下:
UMat addUMats(UMat & M1, UMat & M2){
UMat returnMat;
add(M1, M2, returnMat);
return move(returnMat);}
现在,如果我这样称呼它,那么效果很好:
cv::UMat A = data1;
cv::UMat B = data2;
cv::UMat C = addUMats(A, B);
但是,当我尝试将函数作为参数传递给函数时,我得到一个"参数必须是左值"类型错误。例如,
cv::UMat A = addUMats(addUMats(alpha, beta), addUMats(alpha, beta));
表示任何有效的cv::UMats
,alpha, beta
。
我做了一点research并发现std::move(input)
显式返回一个rvalue类型的临时值。因此,抛出错误是有道理的。
我意识到我可以先解决这个问题:
cv::UMat inputA = addUMats(alpha, beta);
cv::UMat A = addUMats(inputA, inputA);
或者,我甚至可以做类似的事情,
UMat addUMats(UMat & M1, UMat & M2){
UMat returnMat;
add(M1, M2, returnMat);
return returnMat;}
在这种情况下,我理解行[{1}}将导致复制深(?)临时。
所以,我知道可能会有一些OpenCV依赖的东西在这里发生;也许是因为UMat类型有一些时髦的铸造正在进行或类似。
但是,在一般情况下,调整 {/ em>
return returnMat
等函数的最佳方法是什么才能将函数作为对函数的调用?
我在运行时方面寻求最有效的解决方案。另外,我不希望这个问题仅限于OpenCV案例;获得使用addUmats
调用的任何类型的函数的答案将不胜感激。
答案 0 :(得分:2)
我认为你在函数的输入参数中遗漏了一些const
。请尝试如下:
UMat addUMats(const UMat & M1, const UMat & M2) {
UMat returnMat;
add(M1, M2, returnMat);
return move(returnMat);
}
可能不是唯一的问题,但是就目前而言,你的函数不能将临时变量作为输入,因为它假定它们可以在函数内修改。
答案 1 :(得分:1)
当您使用std::move
返回局部变量时,您不允许编译器执行RVO(返回值优化),这是因为您返回的UMat引用与UMat的类型不同,并且标准如果允许编译器执行RVO,则需要返回相同的类型。
如果编译器选择不使用RVO,则返回的对象必须被视为rvalue,因此当允许使用RVO时,将使用复制elision或隐式应用std :: move。
下面:
cv::UMat A = addUMats(addUMats(alpha, beta), addUMats(alpha, beta));
问题在于addUMats
按值返回,而addUMats
接受引用但接受左值引用。解决方案是添加rumue版本的addUMats:
UMat addUMats(UMat && M1, UMat && M2)
答案 2 :(得分:1)
你不能将rvalue传递给你的函数,因为该函数特别需要一个左值(UMat&
)。
以这种方式思考:addUMats
的参数可以在函数内部进行更改。但是当您执行addUMats(addUMats(alpha, beta), addUMats(alpha, beta));
时,您正在使用以后无法访问的两个临时值调用addUMats
。
从概念上讲,添加两个矩阵A和B不应该更改A和B.因此,如果您确定您的同事不会更改函数内的A或B,他们可以将函数的签名更改为:< / p>
UMat addUMats(const UMat & M1, const UMat & M2)
在那种情况下,问题解决了!您可以在两个临时对象上调用addUMats
。因为它们无论如何都不会改变,所以并不重要。
如果您需要优化代码并利用右值优化,您还可以使用以下函数重载该函数:
UMat addUMats(const UMat && M1, const UMat && M2)