C ++ 11 §27.5.4.2/ 21:
void swap(basic_ios& rhs);
效果:应交换
*this
和rhs
的状态,但rdbuf()
将返回与函数调用之前返回的值相同的值,并且rhs.rdbuf()
将返回与函数调用之前返回的值相同的值。
这部分交换对于什么有用?
会引起麻烦吗?
答案 0 :(得分:21)
你可以怪我这个。委员会试图改变(我认为两次),但每次解决方案最终都会破坏。
交换和移动语义在设计完成十年之后被改装到我们的I / O系统上。而且它不是一个完全干净的适合。
请注意,basic_ios::swap
是受保护的成员函数,并且没有名称空间范围变体。因此,这只能从派生类(通常是istream / ostream)调用。请注意,i/o_stream::swap
也受到保护,并且没有名称空间范围变体。他们的规范是调用基类swap
,然后交换任何本地数据(例如gcount
中的istream
)。
最后,在string/filestream
级别,您可以获得“普通”swap
:公共成员和名称空间范围变体。在此级别,您有一个数据成员string/file buffer
(rdbuf
)和基类。此级别的swap
只是交换基础和数据成员。
所有这一切的复杂特征是基类中的rdbuf()
实际上是指向派生类streambuf
(basic_filebuf
或basic_stringbuf
的自引用指针)和 是你不希望基类交换这些自引用指针的原因。
这会使基础swap
变得奇怪,但除了派生客户端之外,每个人都受到保护。而派生客户端swap
的代码随后看起来很简单。在派生级别,swap
被公开,并以公众客户期望的方式行事。
类似的舞蹈用于移动构造和移动分配。由于基类是虚拟基础,因此其构造函数不会被最直接派生的类调用,因此移动构造变得更加复杂。
很有趣。看起来很奇怪。但它最终有效。 ; - )
轻微更正:
Alberto Ganesh Barbati is responsible在swap
级保护i/ostream
。这是他非常好的电话,我完全错过了我的第一个设计。
答案 1 :(得分:2)
我只有一个推测性答案......
如果作者假设某个流可能使用内部缓冲区(例如char buffer[50]
数据成员),则此规定是必要的,因为显然可以交换缓冲区的内容,但它们的地址将保持不变
我不知道是否允许这样做。