在移动赋值中使用std :: swap()会导致无限递归(和原因),但它是Stroustrup的书中的一个例子

Dmi*_*ank 0 c++ recursion move-semantics c++11

我正在努力深入了解如何编写副本并移动构造函数和赋值运算符.

在Bjarne Stroustrup的"The C++ Programming Language - 2013"​​中,我看到了以下移动构造函数和移动赋值的示例:

template<class T, class A>
vector_base<T,A>::vector_base(vector_base&& a)
   : alloc{a.alloc},
   elem{a.elem},
   space{a.space},
   last{a.space}
{
   a.elem = a.space = a.last = nullptr; // no longer owns any memory
}

template<class T, class A>
vector_base<T,A>::& vector_base<T,A>::operator=(vector_base&& a)
{
   swap(?this,a);
   return *this;
}
Run Code Online (Sandbox Code Playgroud)

(旁注:书中似乎有一个拼写错误:::&应该是正确的&,对吧?)

我怀疑它应该导致无休止的递归,因为std::swap()调用移动赋值运算符:

template<typename T>
void swap(T& lhs, T& rhs)
{
  auto temp(lhs);
  lhs = std::move(rhs);
  rhs = std::move(temp);
}
Run Code Online (Sandbox Code Playgroud)

我查了一下,这是一个非常简单的程序:

#include <iostream>
using namespace std;

class TestA {
   int x;

public:
   TestA(int x = 0) : x(x) {
      cout << "TestA value ctor " << x << "\n";
   }

   ~TestA() {
      cout << "TestA dtor " << x << "\n";
   }

   TestA(const TestA &a) : x(a.x) {
      cout << "TestA copy ctor " << x << "\n";
   }

   TestA(TestA &&a) : x(a.x) {
      cout << "TestA move ctor " << x << "\n";
   }

   TestA operator=(const TestA &a) {
      x = a.getX();
      cout << "TestA copy assignment " << x << " = " << a.getX() << "\n";
      return *this;
   }

   TestA &operator=(TestA &&a) {
      cout << "TestA move assignment " << x << " = " << a.getX() << "\n";
      swap(*this, a);
      return *this;
   }

   int getX() const {
      return this->x;
   }

};

int main(void) {
   TestA a{0};
   TestA b{1};
   {
      TestA c{2};
      a = move(c);
   }
}
Run Code Online (Sandbox Code Playgroud)

这产生了以下输出,所以我对无限递归是正确的:

TestA value ctor 0
TestA value ctor 1
TestA value ctor 2
TestA move assignment 0 = 2
TestA move ctor 0
TestA move assignment 0 = 2
TestA move ctor 0
TestA move assignment 0 = 2
TestA move ctor 0
...
...
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?我如何使用swap()内部移动分配?

小智 6

您没有遗漏任何内容,并且接受的答案是错误的。斯特鲁斯特鲁普的书简直太糟糕了。swap()第13章中没有任何地方是独立的;它强烈暗示这swap()std::swap()(就像copy()isstd::copy()等)。这只是一个错误。欢迎来到 C++。


Ded*_*tor 5

你缺少的是Stroustroup swap(TestA&, TestA&)在与类相同的命名空间中提供了一个自由函数.

此外,他不会将其称为std::swap(您的代码也不是),而是使用不合格的id并注入std::swap命名空间using ::std::swap;.

这意味着不使用标准提供的通用版本.