在移动分配中使用 std::swap() 应该会导致无限递归(和原因),但它是 Stroustrup 书中的一个例子
Usage of std::swap() inside move assignment should cause endless recursion (and causes), but it is an example from Stroustrup's book
我正在尝试深入了解我应该如何编写复制和移动构造函数以及赋值运算符。
在 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;
}
(旁注:书中好像有错别字:::&
应该是&
,对吧?)
我怀疑它会导致无限递归,因为 std::swap()
调用移动赋值运算符:
template<typename T>
void swap(T& lhs, T& rhs)
{
auto temp(lhs);
lhs = std::move(rhs);
rhs = std::move(temp);
}
我已经检查过了,这是一个非常简单的程序:
#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);
}
}
这会产生以下输出,所以我对无限递归的看法是正确的:
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
...
...
我错过了什么吗?如何在移动分配中使用 swap()
?
您缺少的是 Stroustroup 在与 class.
相同的命名空间中提供了一个自由函数 swap(TestA&, TestA&)
此外,他没有将其称为 std::swap
(您的代码也没有),而是使用不合格的 ID 并将 std::swap
注入到带有 using ::std::swap;
的命名空间中。
表示没有使用标准提供的通用版本
至少应该是这样。看来独立 swap()
真的不见了。哎哟
您没有遗漏任何内容,接受的答案是错误的。 Stroustrup 的书简直糟透了。第 13 章中的任何地方都没有独立的 swap()
;强烈暗示此 swap()
是 std::swap()
(就像 copy()
是 std::copy()
等)。这只是一个错误。欢迎使用 C++。
我正在尝试深入了解我应该如何编写复制和移动构造函数以及赋值运算符。
在 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;
}
(旁注:书中好像有错别字:::&
应该是&
,对吧?)
我怀疑它会导致无限递归,因为 std::swap()
调用移动赋值运算符:
template<typename T>
void swap(T& lhs, T& rhs)
{
auto temp(lhs);
lhs = std::move(rhs);
rhs = std::move(temp);
}
我已经检查过了,这是一个非常简单的程序:
#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);
}
}
这会产生以下输出,所以我对无限递归的看法是正确的:
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
...
...
我错过了什么吗?如何在移动分配中使用 swap()
?
您缺少的是 Stroustroup 在与 class.
相同的命名空间中提供了一个自由函数swap(TestA&, TestA&)
此外,他没有将其称为 std::swap
(您的代码也没有),而是使用不合格的 ID 并将 std::swap
注入到带有 using ::std::swap;
的命名空间中。
表示没有使用标准提供的通用版本
至少应该是这样。看来独立 swap()
真的不见了。哎哟
您没有遗漏任何内容,接受的答案是错误的。 Stroustrup 的书简直糟透了。第 13 章中的任何地方都没有独立的 swap()
;强烈暗示此 swap()
是 std::swap()
(就像 copy()
是 std::copy()
等)。这只是一个错误。欢迎使用 C++。