为什么 iostream 不可复制?
Why are iostreams not copyable?
使用 rdbuf
和 copyfmt
创建 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++ 最佳实践在设计为不可复制后是否发生了变化?
复制和移动是值语义操作。要定义它们,您首先必须确定 class 的哪些属性赋予其对象不同的值。这一点最初在 iostreams 库中基本上被回避了,然后 C++11 采取了与这种复制构造函数不兼容的不同方向。
流对象的状态包括两部分:指向流缓冲区及其关联状态的指针和格式化信息。自 C++98 起,rdbuf
、rdstate
和 copyfmt
分别公开此信息。
从 C++11 开始,流 classes 也有一个 protected
接口,包括一个移动构造函数(和一个名为 move
的成员),它复制格式 但不是流缓冲区指针。这使 iostream 将格式化信息专门视为流对象的状态。
如果此时将流设置为可复制,它只会执行 copyfmt
而不会执行其他操作。
选择从值状态中排除 rdbuf
可能是由于派生的 class 的值语义更加混乱,例如 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.
语义在某种程度上可能是一致的,但适度的增益会造成很多混乱。
使用 rdbuf
和 copyfmt
创建 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++ 最佳实践在设计为不可复制后是否发生了变化?
复制和移动是值语义操作。要定义它们,您首先必须确定 class 的哪些属性赋予其对象不同的值。这一点最初在 iostreams 库中基本上被回避了,然后 C++11 采取了与这种复制构造函数不兼容的不同方向。
流对象的状态包括两部分:指向流缓冲区及其关联状态的指针和格式化信息。自 C++98 起,rdbuf
、rdstate
和 copyfmt
分别公开此信息。
从 C++11 开始,流 classes 也有一个 protected
接口,包括一个移动构造函数(和一个名为 move
的成员),它复制格式 但不是流缓冲区指针。这使 iostream 将格式化信息专门视为流对象的状态。
如果此时将流设置为可复制,它只会执行 copyfmt
而不会执行其他操作。
选择从值状态中排除 rdbuf
可能是由于派生的 class 的值语义更加混乱,例如 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.
语义在某种程度上可能是一致的,但适度的增益会造成很多混乱。