用例:我正在将数据从我的一个非常旧的程序转换为数据库友好的格式。在某些部分,我必须对旧数据进行多次传递,因为特别是键必须首先存在,然后才能在关系中引用它们。所以我想为什么不在第一次传递期间将不完整的部分放入引用向量中并从工作函数返回它,这样我就可以轻松地使用该向量来对仍然不完整的部分进行第二次传递。我喜欢尽可能避免指针,所以我研究了 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_back
或emplace_back
相反,等等...
有些事情似乎超出了范围,但是什么呢?两者new_data
和old_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/