vector<reference_wrapper> .. 事情超出范围?它是如何工作的?

vector<reference_wrapper> .. things going out of scope? how does it work?

用例:我正在将数据从我的一个非常古老的程序转换为数据库友好格式。有些部分我必须对旧数据进行多次传递,因为特别是键必须首先存在,然后我才能在关系中引用它们。所以我想为什么不在第一次通过时将不完整的部分放在引用向量中,然后 return 它来自工作函数,这样我就可以轻松地使用该向量来进行第二次通过仍然不完整的部分。我喜欢尽可能避免指针,所以我研究了 std::reference_wrapper<T>,这似乎正是我需要的.. 除了我根本不理解它的行为。

我有 vector<OldData> old_datavector<NewData> new_data 作为我的转换成员 class。转换成员函数本质上是:

//...
vector<reference_wrapper<NewData>> incomplete;
for(const auto& old_elem : old_data) {
    auto& new_ref = *new_data.insert(new_data.end(), convert(old_elem));
    if(is_incomplete(new_ref)) incomplete.push_back(ref(new_ref));
}
return incomplete;

但是,incompletefor 循环后立即被破坏。该程序编译,但崩溃并产生乱码。现在我不知道我是否正确放置了 ref,但这只是我尝试将其放置在其他地方的许多尝试之一,使用 push_backemplace_back 代替,等等。 . 有些事情似乎超出了范围,但是什么? new_dataold_data 都是 class 成员,incomplete 也在循环之外,根据文档,reference_wrapper 是可复制的。

这是一个简化的 MWE,它会编译、崩溃并产生乱码:

// includes ..
using namespace std;
int main() {
    int N = 2; // works correctly for N = 1 without any other changes ... ???
    vector<string> strs;
    vector<reference_wrapper<string>> refs;
    for(int i = 0; i < N; ++i) {
        string& sref = ref(strs.emplace_back("a"));
        refs.push_back(sref);
    }
    for (const auto& r : refs) cout << r.get(); // crash & gibberish
}

这是 g++ 10.2.0-std=c++17 如果它有意义的话。现在我可能只使用指针并完成,但我想了解这里发生了什么,文档/搜索似乎没有帮助..

这里的问题是您正在使用 vector 数据结构,每当您添加一个元素时,它可能 re-allocate 存储整个向量,因此该向量上的所有先前引用很可能得到无效,您可以使用 list 而不是 vector.

来解决您的问题