std :: ref和swap函数似乎不能很好地协同工作

时间:2015-12-11 12:52:52

标签: c++ c++11

template <typename T>
void myswap(T a,T b)
{
    T temp = a;
    a = b;
    b = temp;
}
int main()
{
  int m(20),n(30); 
  myswap(ref(m),ref(n));
  //m is still 20 and n is still 30
}

为什么m和n的值没有互换?将包含在std::ref中的值传递给INCREMENT函数会导致原始变量(调用INCREMENT函数的堆栈帧中的变量)中的值更改。或者,std::ref使用是否受到限制/限制?

3 个答案:

答案 0 :(得分:8)

std::ref(及其关联的std::reference_wrapper)是为标准库中的特定用例设计的工具,只应用于那些用户;如果你想在你自己的地方使用它,你必须详细了解它并尊重它的作用。

从根本上说,reference_wrapper更接近指针而不是引用。因此,在交换函数中替换指针,您将看到没有理由认为它实际上会交换:

void myswap(int* a, int* b)
{
    int* temp = a;
    a = b;
    b = temp;
}

答案 1 :(得分:4)

您的代码会创建两个临时std::reference_wrapper对象并交换它们,因此它们会引用不同的对象。所有这一切都是你交换了两个reference_wrapper个对象,而不是它们的目标。

如果手动编写函数模板将生成的内容,行为的原因应该是显而易见的:

void myswap(std::reference_wrapper<int> a, std::reference_wrapper<int> b)
{
  std::reference_wrapper<int> temp = a;
  a = b;
  b = a;
}

显然,这不会更改int个对象,只会更改reference_wrapper个对象。

如果您要执行的操作是强制myswap接受您需要致电myswap<int&>(m, n)的参考,则无法使用reference_wrapper来模仿。但你应该真正修复myswap,因为它现在的写法非常无用。

答案 2 :(得分:1)

您的myswap通过获取元素。

基本上你在函数的本地范围内交换两个引用(std::reference_wrapper s)。

他们指出的价值不会发生变化。

template <typename T> void incrementer(T a) { ++a; } int a = 20;

在这种情况下,转换为int& with

operator T& () const noexcept { return *_ptr; }

在你的代码中,另一方面:

T temp = a;

将简单地调用复制构造函数,复制构造函数复制基础指针:

reference_wrapper(const reference_wrapper&) noexcept = default;

然后,在下一行中再次复制指针:

reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;