首页 > 解决方案 > 带引用的 std::pair 和引用包装器有什么区别

问题描述

我已经陷入了我所做的错误假设。我发现

std::pair<int &, int &>

是一件事。但是我没想到以下会失败

int a = 10;
int b = 20;
int c = 30;

using PRef = std::pair<int &, int &>;

PRef p0 = {a,b};
PRef p1 = {b,c};


EXPECT_EQ(a, 10);
EXPECT_EQ(b, 20);
EXPECT_EQ(c, 30);

p0 = p1;

EXPECT_EQ(a, 10);
EXPECT_EQ(b, 20);
EXPECT_EQ(c, 30);

然而,分配后的第二组测试失败,因为

a is 20 # copied from b
b is 30 # copied from c

我有点期望它的行为类似于引用包装器,其中底层指针将被复制,但这似乎不是它的工作方式。是否有一些明确的理由说明为什么行为与使用不同

std::pair<std::reference_wrapper<int>, std::reference_wrapper<int>>

如果我运行与上面相同的测试但使用 reference_wrapper 则它可以工作。

{
        int a = 10;
        int b = 20;
        int c = 30;

        using PRef = std::pair<std::reference_wrapper<int> , std::reference_wrapper<int>>;

        PRef p0 = {std::ref(a),std::ref(b)};
        PRef p1 = {std::ref(b),std::ref(c)};


        EXPECT_EQ(a, 10);
        EXPECT_EQ(b, 20);
        EXPECT_EQ(c, 30);

        p0 = p1;

        EXPECT_EQ(a, 10);
        EXPECT_EQ(b, 20);
        EXPECT_EQ(c, 30);


    }

这两种形式之间应该有区别吗?

标签: c++std-pairreference-wrapper

解决方案


它具有这种行为的原因与

int a = 10;
int b = 20;

int &aref = a;
int &bref = b;

aref = bref;

分配ab。真实引用(相对于引用包装器)不能被反弹。分配给引用会调用它所引用的赋值运算符。

std::reference_wrapper::operator=重新绑定引用。因此,如果arefbrefstd::reference_wrappers,则分配不会改变a


推荐阅读