c++17 - vector<reference_wrapper> ..事情超出了范围?它是如何工作的?

标签 c++17 reference-wrapper

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

我都有vector<OldData> old_datavector<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_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 数据结构,每当您添加元素时,它都可能会为整个向量重新分配内存,因此该向量上的所有先前引用很可能都会失效,您可以使用 list 而不是 vector 来解决您的问题。

关于c++17 - vector<reference_wrapper> ..事情超出了范围?它是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63306624/

相关文章:

c++ - 无法在 Mac OSX 上使用 clang++ 编译 C++17

c++ - 修改后的 std::invoke/std::apply,将可调用对象作为 void* - 可能吗?

c++ - 在统一的内联初始化中使用不可复制的值初始化静态 std::map

c++ - 将 vector<reference_wrapper<int>> 传递给 vector<int>?

c++ - 在 C++11 中使用 reference_wrapper 而不是标准指针访问类成员

c++ - 在本地使用 reference_wrapper 初始化 vector

c++ - std::reference_wrapper 和多态容器

c++ - header 中的 const 内联 std::map 导致退出时堆损坏

c++ - std::reference_wrapper 和简单指针有什么区别?

c++ - 生成指向回调函数的常量指针数组