【问题标题】:When should I concern myself with std::iostream::sentry?我什么时候应该关注 std::iostream::sentry?
【发布时间】:2011-01-18 21:48:08
【问题描述】:

在线参考对std::iostream::sentry 的用途的描述相当简短和模糊。我什么时候应该关心这个小动物?如果它只打算在内部使用,为什么要公开?

【问题讨论】:

  • 标识符是从什么时候开始的?而且肯定不小! :D

标签: c++ iostream


【解决方案1】:

当您需要使用流提取或输出数据时使用它。也就是说,每当您创建 operator>>(提取运算符)或 operator<<(插入运算符)时。

其目的是简化逻辑:“是否设置了任何失败位?同步缓冲区。对于输入流,可以选择排除任何空白。好的,准备好了吗?”

所有提取流运算符都应以:

// second parameter to true to not skip whitespace, for input that uses it
const std::istream::sentry ok(stream, icareaboutwhitespace);

if (ok)
{
    // ...
}

所有插入流操作符都应该以:

const std::ostream::sentry ok(stream); 

if (ok)
{
    // ...
}

这只是一种更清洁的方式(类似于):

if (stream.good())
{
    if (stream.tie())
        stream.tie()->sync();

    // the second parameter
    if (!noskipwhitespace && stream.flags() & ios_base::skipws)
    {
        stream >> std::ws;            
    }
}

if (stream.good())
{
    // ...
}

ostream 只是跳过空白部分。

【讨论】:

  • 如果我在其他流成员函数方面实现自定义operator>>,是否仍然需要(或一个好主意)使用哨兵?
  • 插入操作符呢? ostream 还定义了哨兵。
  • @GMan:我听到了。似乎可以仅在 iostreams 上编写一整本教科书。 :-)
  • @GMan:至少两次——Teal 的一个旧的(预标准),Langer 和 Kreft 的一个更新的(更大的)讨论标准化版本。
  • @EmileCormier:我要撤销我以前的 cmets。与我之前的建议相反,如果您的操作员是根据现有操作员定义的,则您不需要使用哨兵,我不知道为什么我这么说。
【解决方案2】:

大多数人永远不会编写任何需要处理创建哨兵对象的代码。当/如果您从作为流对象本身基础的流缓冲区中提取数据(或将其插入)时,需要一个哨兵对象。

只要您的插入/提取操作符使用其他 iostream 成员/操作符来完成它的工作,它确实不必处理创建哨兵对象(因为那些其他 iostream 操作符将创建和销毁哨兵对象根据需要)。

【讨论】:

  • 啊,谢谢。这对我来说最有意义(尤其是底层的流缓冲区)。我很困惑为什么教科书的例子展示了如何编写你自己的自定义流操作符从来没有提到哨兵对象。
【解决方案3】:

除基本类型(int、double 等)之外的任何内容的格式化输入都没有多大意义,并且可以说只有在从非交互式流(如 istringstream)中获取时才从它们中获取。所以你可能不应该首先实现 op>>,因此不必担心哨兵对象。

【讨论】:

  • 如果我想让重载运算符>> 方便地对基本类型的元组进行格式化输入怎么办?例如:struct Point{double x, double y}; Point point; file >> point; 重载的 operator>> 是根据基本类型的 operator>> 实现的。
  • @Emile 假设点被格式化为“x,y”,那么实现 op>> 非常困难,因此它可以正确地用于点并且在与所有其他格式化输入运算符一起使用时也可以正常工作。基本上,您最好编写函数来解析您所期望的特定输入,而不是一些最终无法处理现实世界输入的通用方案。
  • @Neil:我明白你在说什么。但也许自定义运算符>> 的合法用途是从对称运算符
  • @Emile 那么序列化是另一回事。通常,它必须在数据之前输出一个标记 - 例如 [POINT]120,70,它可以用来计算出正在读回的东西实际上是什么。当像 Read() 这样的命名函数可能更好时,此类库经常滥用(恕我直言)操作符 op>>。不过,我对 Boost 序列化库一无所知,并且对序列化这个概念有点怀疑
  • @Neil:嗯,等一下,我不太明白你在第一条评论中的论点。 :-) 你是说operator>>(istream& s, P& p){s>>p.x; s>>p.y;} 不好,但getPoint(istream& s, P& p){s>>p.x; s>>p.y;} 没问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 2012-12-23
相关资源
最近更新 更多