我有以下代码:
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)
复制该元素。
要脱离detected
,rect_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_1
和detected
。 struct Rect {
int x;
Rect(Rect&& other) : x(other.x) {
other.x = 0;
}
};
现在它将通过将
other
设置为零来修改other.x
。循环之后,Rect
中的所有detected
都将具有x = 0
。如果您的程序依赖条件x != 0
,则可能会崩溃。 Rect
将具有一个trivial implicitly-declared move constructor,它将仅复制Rect
。因此,从移动构造的 Angular 来看struct Rect {
int x;
};
将与1中的等效。在这种情况下,即使将
detected
的所有元素从中移出也不会对其进行修改。 Simple demo