【问题标题】:Why are iostreams not copyable?为什么 iostreams 不可复制?
【发布时间】:2016-07-03 06:38:55
【问题描述】:

使用rdbufcopyfmt 来制作iostream 对象的本地副本是possible。这允许在本地范围内进行格式更改:

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;
}

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

相关的 C++ 最佳实践被设计为不可复制后是否发生了变化?

【问题讨论】:

  • 好吧,我一定在想别的事
  • 您可能已经命名了该函数克隆,但我当然不会。它当然不符合 OO 克隆概念的语义。
  • @BenjaminLindley 对,iostreams 具有引用语义,此函数通常复制基本切片。这只是一个例子。
  • An istream object, for example, represents a stream of input values, some of which may have already been read, and some of which will potentially be read later. If an istream were to be copied, would that entail copying all the values that had already been read as well as all the values that would be read in the future? The easiest way to deal with such questions is to define them out of existence. Prohibiting the copying of streams does just that --Effective Modern C++(Scott Meyers)
  • 它们是不可复制的,因为它们的资源无法共享而不会带来巨大的开销。指出这一点:如果你销毁os,然后使用cs,它就没有地方可以写了。

标签: c++ iostream copy-constructor


【解决方案1】:

复制和移动是价值语义操作。要定义它们,您首先必须确定类的哪些属性赋予其对象不同的值。起初,iostreams 库很大程度上避开了这一点,然后 C++11 采取了与这种复制构造函数不兼容的不同方向。

流对象的状态包括两部分:指向流缓冲区及其相关状态的指针,以及格式化信息。由于 C++98,rdbufrdstatecopyfmt 分别公开了这些信息。

从 C++11 开始,流类也有一个 protected 接口,包括一个移动构造函数(和一个名为 move 的成员),它复制格式但不复制流缓冲区指针。这使得 iostream 将格式化信息专门视为流对象的状态。

如果此时将流设为可复制,则它只会执行copyfmt 而不会执行其他操作。

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

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.

语义在某种方式上可能是一致的,但如果获得适度的收益,就会造成很多混乱。

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 2020-10-03
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    相关资源
    最近更新 更多