【问题标题】:Why are C++ iostreams always left-hand assigned?为什么 C++ iostream 总是左手分配?
【发布时间】:2014-06-27 21:57:31
【问题描述】:

我正在学习 C++,但从未处理过流。我本来希望符号是:

std::cout << "foo";
char foo << std::cin;

我确定它是 std::cin &gt;&gt; foo 是有充分理由的。这是什么?

【问题讨论】:

  • 将此代码 char&amp; operator&lt;&lt;(char&amp; dst, std::istream&amp; src) { src &gt;&gt; dst; return dst; } 粘贴到您的代码中,然后稍微玩一下 char a; a &lt;&lt; std::cin;。哦,您可能想尝试在a 中移动位。
  • 记住区别的一个方便的方法是操作符指向数据流的方向。 :)

标签: c++ iostream


【解决方案1】:

这与 > 运算符的关联性有关。

它们最初仅用于左关联的位移。重载时运算符的关联性保持不变(否则代码将无法解析):

如果你这样做了

 int a, b ;
 a << b << cin

你会得到

(a << b) << cin

位移位和输入

这就是标准库这样做的原因。

【讨论】:

  • 这里要强调的是,流是库的一部分,而不是基础语言,因此该语言不支持语法完全匹配语义的唯一运算符。 &lt;&lt; 实际上实际上是移位运算符的重载,而不仅仅是以两种不同方式使用的语言功能。
【解决方案2】:

a &lt;&lt; ba &gt;&gt; b 只是以下的简写:

operator<<(a,b)

operator>>(a,b)

(或成员函数等价物)。

也就是说,它们只是对特定函数的调用。恰巧C++ 标准库重载operator&lt;&lt; 以执行到ostreams 的输出流,以及operator&gt;&gt; 执行来自istreams 的输入流。

这些函数仅重载以使流位于左侧。

做出这个决定有两个原因。首先是符号的简单性(也就是说,由于只有一种对操作数进行排序的方式,因此对于任何特定代码的含义都不会产生歧义,并且在将标准库扩展为支持一个额外的类)。第二个是&lt;&lt;&gt;&gt; 是左关联的,所以:

int a, b;
a << b << cin;

会变成:

(a << b) << cin;

同时:

int a, b;
cin >> b >> a;

正确变成:

(cin >> b) >> a;

【讨论】:

    【解决方案3】:

    所以你将不得不按照上帝的意图将控制台放在左侧! :)

    它实际上与称为运算符重载的东西有关。如果您只是学习 C++,您可能还没有涵盖这些内容,因此请在“我稍后会得到的东西”下记录我要说的内容。

    C++ 位于 C 之上。在 C 中,&lt;&lt;&gt;&gt; 只是位移运算符。在 c++ 中它可以更多。 std:cout &lt;&lt; foo 不是 C,而是 C++。它是 C++ 的原因是因为 std::cout 对象重载了 &lt;&lt; 运算符以表示位移以外的其他含义。

    换句话说,&lt;&lt; 仅表示将foo 发送到cout,因为cout 表示就是这个意思。 &lt;&lt; 实际上是 cout 类的一个函数。

    就好像你说的是std::cout-&gt;sendThatToMe(foo)

    在整个事件中,foo 只是一个不幸的参数,对于 &lt;&lt; 的含义没有发言权。这就是为什么你不能以其他方式做到这一点。如果你这样做了,就好像你在说这个:

    foo->sendMeToThat( std::cout).
    

    如果您将该功能(实际上是&gt;&gt; 运算符)添加到您可能想要发送到控制台的每个臭对象,则可以使其工作。哦,祝你好运。

    因此,虽然我认为将控制台的东西保留在左侧有很好的风格原因,但实际上它必须是这样的技术原因。这是因为被重载的运算符已经是关联的。自从在旧的 C 时代它们被用来移动位以来,它们就一直存在。重载它们并不能改变它们的关联性。

    【讨论】:

      【解决方案4】:

      这正是他们应该工作的方式。我认为这样做是为了清楚地区分输入操作 ( >> ) 和输出操作 ( 如果您以这种奇特的方式重载 &lt;&lt; 运算符(正如在 cmets 中明显的船长建议的那样):

      template<typename T>
      std::istream& operator<<( T& data , std::istream& is )
      {
          is >> data;
          return *this;
      }
      

      操作是输入还是输出就不太清楚了(使用std::cin std::cout 很简单,但是关于两个名为file1file2 的流,一个用于读取,一个用于写入):

      a << std::cin;
      std::cout << a;
      
      a << file;
      file << a;
      

      【讨论】:

        猜你喜欢
        • 2011-07-26
        • 1970-01-01
        • 1970-01-01
        • 2017-03-27
        • 1970-01-01
        • 2019-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多