1

我正在尝试在 C++ 中使用引用包装器,因为我希望能够直接更改对象的值,但它们的值都是错误的。这是一个演示此问题的示例:

#include <vector>
#include <functional>
#include <iostream>
using namespace std;

int main() {
    vector<int> v1 = {1, 2, 3};
    for (int i : v1) {
        cout << i << " ";
    }
    cout << endl;

    vector<reference_wrapper<int>> v2;
    for (int i : v1) {
        v2.push_back(i);
    }
    for (int i : v2) {
        cout << i << " ";
    }
}

它打印

1 2 3
3 3 3

我不确定为什么引用包装向量v2没有复制引用的值v1...

编辑:这是另一个神秘地不起作用的例子。我认为这一篇中没有任何悬而未决的参考资料。

#include <vector>
#include <functional>
#include <iostream>
using namespace std;

int main() {
    vector<int> v1;
    vector<reference_wrapper<int>> v2;

    for (int i = 0; i < 3; i++) {
        v1.push_back(i);
        v2.push_back(v1[i]);
    }

    for (int i : v2) {
        cout << i << " ";
    }
}

它打印9596312 1 2,而我希望它打印0 1 2......

4

2 回答 2

3

for循环中

for (int i : v1) {
    v2.push_back(i);
}

您正在reference_wrapper从局部变量 s 构造 s ,该变量i在迭代后立即被销毁,因此reference_wrapper存储的 sv2被悬空。对它们的取消引用会导致未定义的行为

您应该声明i为参考

for (int& i : v1) {
    v2.push_back(i);
}

居住


对于您的编辑,请注意这std::vector::push_back可能会导致重新分配 on v1,这会使存储的引用引用v2dangled 的元素v1

您可以reserve提前使用以避免重新分配。例如

vector<int> v1;
v1.reserve(3);
vector<reference_wrapper<int>> v2;

for (int i = 0; i < 3; i++) {
    v1.push_back(i);
    v2.push_back(v1[i]);
}

居住

于 2020-03-19T05:36:34.160 回答
1

这个:

    vector<reference_wrapper<int>> v2;
    for (int i : v1) {
        v2.push_back(i);
    }

构造一个reference_wrapper<int>per push_back。这将是i对循环中的引用。碰巧的是,您的编译器实现很可能碰巧为作用域变量重用了相同的内存地址i

引用仍将在循环之后引用该地址 - 在循环结束时恰好未触及,因此最后一个值i就是存储在那里的值。

它会导致程序通过引用(或通过任何其他方式)在该地址读取/写入未定义的行为,并且一个未定义的行为是您实际上可以读取内存并从中获取看起来熟悉的值。

该变量i在循环后已死,因此您应该以相同的方式处理对它的引用。他们都在风中飘荡……

于 2020-03-19T05:57:02.927 回答