我有以下代码:


vector <Rect> detectAndDisplay(Mat frame) {
    Mat frame_gray;
    vector <Rect> detected;


    //load the cascade
    if (!cascade.load(CASCADE_NAME)) {
        printf("--(!)Error loading Cascade\n");
        std::exit(0);
    };


    // 2. Perform Viola-Jones Object Detection
    cascade.detectMultiScale(frame_gray, detected, 1.1, 1, 0 | CV_HAAR_SCALE_IMAGE, Size(50, 50), Size(500, 500));


    // 2.5 Merge overlapping rectangles
    groupRectangles(detected, 1, 0.8);
    std::vector <Rect> singles;
    std::vector <Rect> overlaps;
    for (auto rect_1: detected) {
        bool isSingle = false;
        for (auto rect_2: detected) {
            if (rect_1 == rect_2) {
                continue;
            }
            bool intersects = ((rect_1 & rect_2).area() > 0);
            if (intersects) {
                isSingle = false;
                break;
            }
        }
        if (isSingle) {
            singles.push_back(std::move(rect_1)); //MOVING
        } else {
            overlaps.push_back(std::move(rect_1));
        }
    }

    // 4. Draw box around faces found
    for (int i = 0; i < detected.size(); i++) {
        rectangle(frame, Point(detected[i].x, detected[i].y),
                  Point(detected[i].x + detected[i].width, detected[i].y + detected[i].height),
                  Scalar(0, 255, 0), 2);
    }
    return detected;
}

当我编译并运行时,第4步工作正常。我的问题是,为什么?我已将的内容移至两个不同的 vector 中。因此,我期待遇到段错误。

最佳答案



你还没有无论detected是否具有move构造函数,都不会在循环中修改Rect

首先,使用for (auto rect_1: detected)复制一个 vector 元素( auto is not a reference),然后使用std::move(rect_1)复制该元素。

要脱离detectedrect_1应该是一个引用:for (auto& rect_1: detected)

假设您已经修复了for循环,并且detected元素已从中移出。

  • 假设Rect看起来像这样:
    struct Rect {
        int x;
        Rect(Rect&& other) : x(other.x) { }
    };
    

    此move-constructor不会修改other,因此.push_back(std::move(rect_1))不会修改rect_1detected
  • 假设我们以不同的方式定义move构造函数:
    struct Rect {
        int x;
        Rect(Rect&& other) : x(other.x) {
            other.x = 0;
        }
    };
    

    现在它通过将other设置为零来修改other.x。循环之后,Rect中的所有detected都将具有x = 0。如果您的程序依赖条件x != 0,则可能会崩溃。
  • 如果您根本不声明move构造函数,则Rect将具有一个trivial implicitly-declared move constructor,它将仅复制Rect。因此,从移动构造的 Angular 来看
    struct Rect {
        int x;
    };
    

    将与1中的等效。在这种情况下,即使将detected的所有元素从中移出也不会对其进行修改。

  • Simple demo

    10-07 22:48