1

我正在尝试编写一个返回最大检测对象中心点的函数。这里没问题。问题是如果用户想要使用它,我还想从参数中返回前景掩码。

为了处理这种情况,我的解决方案如下:

cv::Point detect(const cv::Mat &img, cv::Mat &mask = *new cv::Mat());

如果mask指定了参数,则可以在main. RAII 在其他情况下是否有效,还是会出现内存泄漏?

注意:我知道我可以将函数重载 2 行,但我想知道是否可以通过使用默认参数而不是使用指针来正确执行此操作(输入类型是严格的)。

另一个注意事项:如果cv::noArray()可以使用或类似的功能,那是完全可以的。

示例用法:

char ch = 0;
while (ch != 27) // ESC is pressed
{
    cap >> img;
    if (img.empty())
        break;
    cv::Mat mask;
    cv::Point pt = detect(img, mask);
    // or pt = detect(img);
    cv::imshow("original", img);
    cv::imshow("foreground", mask);
    ch = cv::waitKey(1);
}
4

2 回答 2

1

是的,这引入了内存泄漏。您可能会考虑使用元组返回值:

std::tuple<cv::Point, cv::Mat> detect(const cv::Mat &img);

或制作mask指针:

cv::Point detect(const cv::Mat &img, cv::Mat *mask = nullptr);

您也可以尝试使用演员表保持相同的签名。这很丑陋,但它可能会起作用:

cv::Point detect(const cv::Mat &img, cv::Mat &mask = const_cast<cv::Mat&>(static_cast<cv::Mat const&>(cv::Mat())));
于 2020-10-11T19:39:57.053 回答
1

丑陋,但没有内存泄漏:

cv::Point detect(const cv::Mat &img, cv::Mat &mask = *std::make_unique<cv::Mat>());

如果用户不提供掩码,则会创建一个掩码。detect将写回掩码,然后立即销毁。使用重载会更有效,因为它可以跳过不必要的更新。

或者,使用cv::Mat* mask = nullptr. 我不知道您所说的“(输入类型是严格的)”是什么意思。但是对于有经验的 C++ 程序员来说,cv::Mat* mask = nullptr模式很清楚:可选的 out 参数,没有隐含的所有权转移。

于 2020-10-12T14:55:30.653 回答