为什么`basic_ios :: swap`只进行部分交换?

Che*_*Alf 18 c++ swap c++11

C++ 11§27.5.4.2/ 21:

void swap(basic_ios& rhs);

效果:*thisrhs将被交换的状态,除了它rdbuf()应返回与函数调用之前rhs.rdbuf()返回的值相同的值,并且应返回与函数调用之前返回的值相同的值.

这部分交换对什么有用?

它会引起麻烦吗?

How*_*ant 21

你可以责怪我这个.委员会试图改变(我认为两次),但每次解决方案最终破坏了事情.

交换和移动语义在设计完成十年后被改装到我们的I/O系统上.而且它不是一个完全干净的合身.

请注意,它basic_ios::swap受保护的成员函数,并且没有名称空间范围变体.因此,这只能从派生类(通常是istream/ostream)调用.请注意,i/o_stream::swap它也受到保护,没有名称空间范围变体.他们的规范是调用基类swap然后交换任何本地数据(例如gcountin istream).

最后,在string/filestream您可以认为是"正常" 的级别上swap:公共成员和名称空间范围变体.在这个级别,你有一个数据成员string/file buffer(rdbuf)和基类.在swap在此级别简单地交换基座和数据成员.

所有这一切的复杂特征是rdbuf()基类中的down实际上是指向派生类streambuf(basic_filebufbasic_stringbuf)的自引用指针,就是为什么你不希望基类交换这些自引用指针的原因.

这使得基础swap很奇怪,但除了派生客户端之外,每个人都受到保护.然后,派生客户端的代码swap看起来很简单.在派生级别,swap公开并以公共客户期望的方式行事.

类似的舞蹈是为移动建筑和移动任务.由于基类是虚拟基础,因此其构造函数不会被最直接派生的类调用,因此移动构造变得更加复杂.

好玩.看起来很奇怪.但它最终有效.;-)

轻微修正:

Alberto Ganesh Barbati 负责保护swapi/ostream级别.这是他非常好的电话,我完全错过了我的第一个设计.