1

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

我两者都有vector<OldData> old_data,并且vector<NewData> new_data是我的转换班的成员。转换成员函数本质上是:

//...
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;

但是,在循环incomplete之后立即被打破。for该程序编译,但崩溃并产生乱码。现在我不知道我ref是否正确放置,但这只是我尝试将它放在其他地方的众多尝试之一,使用push_backemplace_back代替等。.. 似乎有些东西超出了范围,但是什么?两者都是类成员,new_data也存在于循环之外,并且根据文档,是可复制的。old_dataincompletereference_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现在我可能只使用指针并完成,但我想了解这里发生了什么,文档/搜索似乎没有帮助..

4

1 回答 1

1

这里的问题是您使用的vector数据结构可能会在您添加元素时为整个向量重新分配内存,因此该向量上的所有先前引用很可能会失效,您可以通过使用list代替来解决您的问题vector

于 2020-08-07T22:03:06.747 回答