繁体   English   中英

在嵌套循环中使用 for auto

[英]Using for auto in nested loops

美好的一天,我最近一直在尝试转向 C++ 以加速我的一些应用程序。 可能是由于缺乏背景知识,我犯了这样一个愚蠢的错误,但是,在尝试使用嵌套循环运行它时,我interrupted by signal 11: SIGSEGV

mongocxx::cursor cursor = coll.find({});
for(auto doc : cursor) {
    std::cout << "TEST FIRST" << bsoncxx::to_json(doc) << "\n";
    for (auto doc2 : cursor) {
        std::cout << "FIRST: " << bsoncxx::to_json(doc) << "\n";
        std::cout << "SECOND: " << bsoncxx::to_json(doc2) << "\n";
    } }

我到底做错了什么,为什么?

您代码中的问题是您在两个循环中都在cursor上迭代,但是来自mongocxx文档:

[...] 取消引用任何非 end() 迭代器总是会给出游标中的第一个剩余文档。 增加一个非结束迭代器相当于增加所有迭代器。

[...] 如果 begin() 被多次调用,cursor::iterator 返回的指向下一个剩余的结果,而不是对 begin() 的原始调用的结果。

在 C++ 中,范围循环只是使用迭代器的一种隐藏方式,问题在于(根据上面的引用),当您增加内循环迭代器时,实际上是在增加外循环迭代器。 您的代码(大约)相当于:

for (auto it = cursor.begin(); it != cursor.end(); ++it) {
    // there may or may not be a ++it here, that does not change the explanation
    // but the documentation of mongocxx is unclear on this
    for (++it; it != cursor.end(); ++it) { }
}

问题是,当内循环到达cursor.end() ,你在外循环中增加it ,然后再次将它与cursor.end()进行比较,这可能就是你得到SIGSEV

做你想做的唯一方法是要么有两个游标,要么把所有东西都存储在一个容器中(例如,一个std::vector ),然后迭代这个向量(你不会遇到与std::vector相同的问题) std::vector )。


关于评论中提到的const&的旁注 - 当您执行for(auto doc: cursor) ,这等效于(不完全是,但您会明白):

for (auto it = cursor.begin(); it != cursor.end(); ++i) {
    auto doc = *it; // here, you make a copy of *it, this is expensive
}

const auto&替换auto改变了doc的声明,并使它成为对迭代器指向的值的引用。

除了我上面提到的其他问题,这会给你不正确的结果,因为当你在内循环中迭代时,你实际上也在增加外循环迭代器,所以外循环doc引用要么指向某些东西不再存在(UB)或指向新迭代器的底层对象,实际上是doc2 ,因此您将拥有&doc == &doc2 ,即docdoc2都将指向同一个对象(同时具有const auto& )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM