std::swap 在 VS 2013 中导致无限递归
std::swap causes infinite recursion in VS 2013
请考虑以下代码片段:
#include <utility>
struct foo
{
foo()
{
}
foo(foo&& other)
{
std::swap(*this, other);
}
};
int main(int argc, char** argv)
{
foo f(std::move(foo()));
}
它在VS2013中导致无限递归,但无法使用g ++/clang进行编译,并出现删除operator=
的错误(这是有道理的):
In file included from /usr/local/include/c++/5.3.0/bits/stl_pair.h:59:0,
from /usr/local/include/c++/5.3.0/utility:70,
from main.cpp:1:
/usr/local/include/c++/5.3.0/bits/move.h: In instantiation of 'void std::swap(_Tp&, _Tp&) [with _Tp = foo]':
main.cpp:11:26: required from here
/usr/local/include/c++/5.3.0/bits/move.h:186:11: error: use of deleted function 'foo& foo::operator=(const foo&)'
__a = _GLIBCXX_MOVE(__b);
^
main.cpp:3:12: note: 'foo& foo::operator=(const foo&)' is implicitly declared as deleted because 'foo' declares a move constructor or move assignment operator
struct foo
^
In file included from /usr/local/include/c++/5.3.0/bits/stl_pair.h:59:0,
from /usr/local/include/c++/5.3.0/utility:70,
from main.cpp:1:
/usr/local/include/c++/5.3.0/bits/move.h:187:11: error: use of deleted function 'foo& foo::operator=(const foo&)'
__b = _GLIBCXX_MOVE(__tmp);
^
我认为这是一个VS错误。但是,该标准是否对如何实施std::swap
施加了任何规则?我的意思是这仅仅是 VS 中的错误实现还是违反标准?
是的,这段代码不应该编译,因为根据 C++14 标准草案 N4140 [utility.swap]/2:
要求:
T
型应为MoveConstructible
型(表 20)和MoveAssignable
型(表 22)。
C++11 包含相同的要求。
所以这确实是VS2013中的一个错误,实际上在VS2015中已经修复。
但是,在添加如下所示的移动分配运算符后:
foo& operator=(foo&& other) = default;
您将在GCC,Clang和VS2015(DEMO)中获得无限递归。
人们可以很容易地猜到,由于swap()
需要MoveConstructible
和MoveAssignable
,它在内部使用移动构造函数和/或移动赋值运算符,因此通过调用this
和参数的swap()
来实现它们绝对是非法的。
相关文章:
- 交换运算符 + 重载会导致无限递归
- 为什么当函数参数未定义为常量引用时存在无限递归?
- 递归应用 C++20 范围适配器会导致编译时无限循环
- 为什么这个递归函数会创建一个无限循环?
- 计算递归和时的无限循环
- 为什么这是无限递归
- C 递归函数无限循环
- 尝试"复制"shared_ptr向上转换行为会导致复制构造函数上的无限递归(导致段错误)
- ConstexPR模板功能的无限递归
- 交换和移动无限递归
- 无限循环与无限递归.两者都未定义吗?
- 函数中的无限递归
- 无限模板递归,因为没有布尔表达式优化,只有 gcc
- 运算符重载流提取运算符 (>>) C++会导致无限递归流提取
- C 无限环路:递归函数
- 实现递归函数,避免由 C++ 中 include 的循环调用(没有 #pragma 一次)引起的无限循环输入
- C :Ostream无限递归
- 无限递归模板实例化使用clang时GCC工作正常
- 当我使用 boost 构建绝对路径时,无限递归
- 模板中的无限递归