简体   繁体   English

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

[英]Why does `basic_ios::swap` only do a partial swap?

C++11 §27.5.4.2/21: C ++ 11§27.5.4.2/ 21:

void swap(basic_ios& rhs);

Effects: The states of *this and rhs shall be exchanged, except that rdbuf() shall return the same value as it returned before the function call, and rhs.rdbuf() shall return the same value as it returned before the function call. 效果: *thisrhs的状态应该被交换,除了rdbuf()将返回与函数调用之前返回的值相同的值,并且rhs.rdbuf()将返回与函数调用之前返回的值相同的值。

What is this partial swapping useful for? 这部分交换对什么有用?

Can it cause trouble? 它会引起麻烦吗?

You can blame me for this one. 你可以责怪我这个。 The committee has tried to change (twice I think), but each time the solution ended up breaking things. 委员会试图改变(我认为两次),但每次解决方案最终破坏了事情。

Swap and move semantics was retrofitted onto our I/O system a decade after it was designed. 在设计完成十年后,交换和移动语义被改装到我们的I / O系统上。 And it wasn't a perfectly clean fit. 而且它不是一个完全干净的合身。

Note that basic_ios::swap is a protected member function and there is no namespace-scope variant. 请注意, basic_ios::swap受保护的成员函数,并且没有名称空间范围变体。 Thus this can only be called from a derived class (typically istream/ostream). 因此,这只能从派生类(通常是istream / ostream)调用。 Note that i/o_stream::swap is also protected and with no namespace-scope variant. 请注意, i/o_stream::swap也受到保护,并且没有名称空间范围变体。 And their spec is to call the base class swap and then swap any local data (such as the gcount in istream ). 他们的规范是调用基类swap然后交换任何本地数据(例如istreamgcount )。

Finally up at the string/filestream level you get what you would consider a "normal" swap : public member and namespace-scope variants. 最后在string/filestream级别,您将获得您认为是“正常” swap :公共成员和名称空间范围变体。 At this level you've got a data member string/file buffer (the rdbuf ) and the base class. 在这个级别,你有一个数据成员string/file bufferrdbuf )和基类。 The swap at this level simply swaps the base and data members. 此级别的swap只是交换基础和数据成员。

The complicating characteristic of all this is that the rdbuf() down in the base class is actually a self-referencing pointer to the derived class's streambuf ( basic_filebuf or basic_stringbuf ) and that is why you don't want the base class to swap these self-referencing pointers. 所有这一切的复杂特征是基类中的rdbuf()实际上是一个指向派生类的streambufbasic_filebufbasic_stringbuf )的自引用指针, 就是为什么你不希望基类交换这些自我 - 引用指针。

This makes the base swap weird, but everyone is protected from it except the derived clients. 这使得基础swap很奇怪,但除了派生客户端之外,每个人都受到保护。 And the code for the derived client's swap is subsequently deceptively simple looking. 然后,派生客户端swap的代码看起来很简单。 And at the derived level, swap is made public and behaves in the manner that public clients expect it to. 在派生级别, swap是公开的,并且以公共客户期望的方式行事。

A similar dance is made for move construction and move assignment. 类似的舞蹈是为移动建筑和移动任务。 Move construction is further complicated by the fact that the base class is a virtual base, and thus its constructor is not called by the most directly derived class. 由于基类是虚拟基础,因此其构造函数不会被最直接派生的类调用,因此移动构造变得更加复杂。

It was fun. 好玩。 It looks weird. 看起来很奇怪。 But it ultimately works. 但它最终有效。 ;-) ;-)

Slight Correction: 轻微修正:

Alberto Ganesh Barbati is responsible for protecting swap at the i/ostream level. Alberto Ganesh Barbati 负责保护i/ostream级别的swap It was a very good call on his part that I had completely missed with my first design. 这是他非常好的电话,我完全错过了我的第一个设计。

I only have one speculative answer... 我只有一个推测性答案......

If the author assumed that a stream may use an internal buffer (for example a char buffer[50] data member), then this provision is necessary as obviously the content of the buffers may be swapped, but their address will remain unchanged. 如果作者假设流可以使用内部缓冲区(例如char buffer[50]数据成员),那么这个规定是必要的,因为显然可以交换缓冲区的内容,但是它们的地址将保持不变。

I do not know whether it is actually allowed or not. 我不知道它是否真的被允许。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM