【问题标题】:Why can't std::ostream be moved?为什么 std::ostream 不能移动?
【发布时间】:2014-01-13 12:06:42
【问题描述】:

显然,流无法复制。应该可以移动流。根据 27.9.1.11 [ofstream.cons] 第 4 段,可以移动构造 std::ofstreamstd::ifstreamstd::fstreamstd::*stringstream 变体也是如此)。例如:

#include <iostream>
#include <fstream>
#include <string>

std::ofstream makeStream(std::string const& name) {
    return std::ofstream(name);
}

int main()
{
    std::ofstream out{ makeStream("example.log") };
}

尝试移动 std::ostream,例如,让工厂函数根据作为参数传递的 URN 创建 std::ofstreamstd::ostringstream 或其他一些流是行不通的。 std::ostream(嗯,类模板 std::basic_ostream 真的)根据 27.7.3.1 [ostream] 有一个 protected 移动构造函数。

为什么std::ostream 不能自己移动?

【问题讨论】:

  • 您会将std::ostream 移动到什么位置?您需要创建派生类的实例,除非我误解了您,并且如果您在编译时不知道派生类,那么移动将如何工作?
  • @hvd:我当然可以创建std::ostream 类型的对象,例如,使用std::ostream out(new std::filebuf("example.log"));(请注意,此代码需要一些工作以避免内存泄漏,但可以通过注册合适的回调)。
  • 您在问题中提到了ofstream/ostringstream,而不是直接提到了ostream。这对他们有什么作用?
  • @hvd:根据您的论点,只有 final 类应该是公开可移动的,而其他类型肯定不是这种情况(例如 std::stringstd::vector&lt;T&gt; 尽管这可能是不明智的首先从这些类派生)。尽管霍华德发布的链接指出了其他问题,但我怀疑可能会意外切割流。
  • 哦,我不是说它应该是公开移动的,也不应该是公开移动的。我是说我认为即使它可以公开移动,它也不适合你(根据你在问题中提出的内容)。

标签: c++ c++11 iostream


【解决方案1】:

最初它们是可移动的。结果证明这是我的设计缺陷,由 Alberto Ganesh Barbati 发现:

http://cplusplus.github.io/LWG/lwg-defects.html#911

该问题显示了一些示例,其中ostream 被移动和/或交换,结果令人惊讶,而不是预期。我确信这些类型不应该是公开移动的,也不能通过这个问题交换。

【讨论】:

  • 嗯。我看到了问题,但我不确定我是否同意解决方案是让它们不可移动。相反,应该更改实现以使代码具有预期的行为(我假设通过擦除流的实际类型)。 FWIW Dietmar 提出了一个引人注目的用例,说明为什么流应该是可移动的(我之前也遇到过同样的问题)。
  • @KonradRudolph:问题在于自定义流缓冲区通常嵌入到实际对象中,而不是在堆上分配。强制std::ostreams 可移动将强制流缓冲区以不同方式分配,这是不可行的(对于标准流类可能可行,但对于现有用户定义的流不可行)。我想,返回未知类型流的用例最好以不同的方式解决。
  • @HowardHinnant 派生的ofstream 仍然可以移动吗?
  • @Koushik:是的,ofstream(和其他“具体”流类型)是可移动和可交换的。
  • 这是一个很好的副作用,但它从来都不是一个激励因素。无论如何,人们都可以对std::cout 做相当具有破坏性的事情。例如std::cout.rdbuf(nullptr); 仍然是完全合法的(但不可取)。
猜你喜欢
  • 1970-01-01
  • 2015-04-30
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
  • 2014-04-25
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
相关资源
最近更新 更多