为什么iostream无法复制? [英] Why are iostreams not copyable?

查看:94
本文介绍了为什么iostream无法复制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能使用<$ c制作iostream对象的本地副本$ c> rdbuf 和 copyfmt 。这允许格式更改在本地范围内:

  std :: ostream&运算符<< (std :: ostream& os,foo const& smth){
cloned_ostream cs(os);
cs<< std :: hex<< smth.num;
//操作系统未切换为十六进制,这是一个令人困惑的副作用
return os;
}

为什么流类不提供复制构造函数来做到这一点? p>

自从将C ++最佳实践设计为不可复制以来,相关的C ++最佳实践是否已更改?

解决方案

复制和移动是价值语义操作。要定义它们,首先必须确定一个类的哪些属性为其对象提供不同的值。最初,这一点在iostreams库上大为回避,然后C ++ 11采取了与这种复制构造函数不兼容的另一个方向。



流对象的状态包括两部分:指向具有其关联状态的流缓冲区的指针,以及格式化信息。自C ++ 98起, rdbuf rdstate copyfmt 分别公开此信息。



自C ++ 11起,流类还具有受保护的 接口,包括移动构造函数(和一个名为 move 的成员),它复制格式但不复制流缓冲区指针



如果这时使流成为可复制的,则它只会做 copyfmt 而不是其余。



选择从值中排除 rdbuf 状态可能是由于派生类(例如 std :: fstream )的值语义进一步混乱,它不仅公开了对流缓冲区的访问,还嵌入并拥有它

  std :: ifstream f(path + filename);。 //拥有文件,甚至是文件。 
std :: istream i = f; //观察外部管理的文件。

std :: istream i2 = i; //确定,复制一个浅引用。
std :: ifstream f2 = f; //错误,ifstream不只是一个浅引用。

std :: istream i3 = std :: move(f); //错误?将保留对右值的引用。
std :: ifstream f3 = std :: move(f); // OK:完整副本,包括文件缓冲区。

语义在某些方面可能是一致的,但是对于中等程度的收益会造成很多混乱


It's possible to make a local copy of an iostream object, using rdbuf and copyfmt. This allows formatting changes to be locally scoped:

std::ostream & operator << ( std::ostream & os, foo const & smth ) {
    cloned_ostream cs( os );
    cs << std::hex << smth.num;
    // os is not switched to hexadecimal, which would be a confusing side-effect
    return os;
}

Why don't the stream classes provide copy constructors to do this?

Have relevant C++ best practices changed since they were designed as non-copyable?

解决方案

Copying and moving are value-semantic operations. To define them, you first have to decide what properties of a class give its objects distinct values. This point was at first largely sidestepped for the iostreams library, and then C++11 took a different direction incompatible with such a copy constructor.

The state of a stream object comprises two parts: A pointer to a stream buffer with its associated state, and formatting information. Since C++98, rdbuf, rdstate, and copyfmt expose this information separately.

Since C++11, stream classes also have a protected interface including a move constructor (and a member called move) which copies the format but not the stream buffer pointer. This commits iostream to treating the formatting information exclusively as the state of the stream object.

If streams were made copyable at this point, it would only do copyfmt and not the rest.

The choice to exclude rdbuf from the value state may be due to the further-muddled value semantics of derived classes such as std::fstream, which not only expose access to a stream buffer, but also embed and own it.

std::ifstream f( path + filename ); // Owns, or even "is," a file.
std::istream i = f; // Observes an externally-managed file.

std::istream i2 = i; // OK, copy a shallow reference.
std::ifstream f2 = f; // Error, ifstream is more than a shallow reference.

std::istream i3 = std::move( f ); // Error? Would retain a reference to an rvalue.
std::ifstream f3 = std::move( f ); // OK: full copy including the file buffer.

The semantics could be consistent in some fashion, but it would be a lot of confusion for a moderate gain.

这篇关于为什么iostream无法复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆