问题确实在标题中;我确定这是合乎逻辑的,但是现在我很困惑!
read()
和函数如何write()
?我认为用户定义的运算符应具有与内置运算符相似的语义,例如+
可以用于添加复数或几何矢量。但是ostream::operator<<
与位移无关。现在,一些早期的C ++设计决策被认为是有问题的,例如,如果存在析构函数,则自动生成副本构造函数,因此选择不必一定有逻辑operator<<
。
问题确实在标题中;我确定这是合乎逻辑的,但是现在我很困惑!
read()
和函数如何write()
?我认为用户定义的运算符应具有与内置运算符相似的语义,例如+
可以用于添加复数或几何矢量。但是ostream::operator<<
与位移无关。现在,一些早期的C ++设计决策被认为是有问题的,例如,如果存在析构函数,则自动生成副本构造函数,因此选择不必一定有逻辑operator<<
。
Answers:
根据《 C ++的设计和演进》第8.3.1节:
Doug McIlroy提出了提供输出运算符而不是命名输出函数的想法,类似于UNIX Shell中的I / O重定向运算符(>,>>,|等)。
[...]
考虑了几种用于输入和输出操作的运算符:赋值运算符是输入和输出的候选者,但绑定方式错误。那
cout=a=b
将被解释为cout=(a=b)
,并且大多数人似乎更喜欢输入运算符与输出运算符不同。运算符<
和>
经过了尝试,但是“小于”和“大于”的含义已深深地扎根在人们的脑海中,以至于新的I / O语句出于所有实际目的都是不可读的(<<
and似乎并非如此>>
) 。除此之外,大多数键盘上的'<'都在','上方,人们在写这样的表达式:
cout < x , y, z;
为此,给出好的错误消息并不容易。
也许是因为它看起来与Unix追加操作类似,因为您实际上是在追加到输入/输出流?
例如
echo "foo" >> bar
sendmail -f test@domain.com << myemail.txt
(从Zac Howland窃取输入示例)
<<
在UNIX命令行上使用进行插入: sendmail -f test@domain.com << myemail.txt
。
->
已经具有现有意为好,这样做的标记对<-
因此,请记住,如果您将其cin
视为键盘和cout
显示器,则将键入的内容输入变量
cin>>var;
或变量的内容进入屏幕
cout<<var;
因为它们或多或少都具有合理的优先级并且看上去不错。在C ++中,您不能创建新的运算符或更改其优先级或分组规则,只能重载现有运算符并更改其实际功能。
选择<<
和>>
具有一些不幸的副作用,因为它在某种程度上推动了将遵循顺序完成输出的想法。尽管由于巧妙的链接技巧而对于实际输出而言是正确的,但是对于所涉及的计算却是错误的,这通常令人惊讶。
更具体地写
std::cout << foo() << bar() << std::eol;
并不暗示foo
会在之前被调用bar
。
使用C ++ 17,序列问题已“修复”。现在,对于<<
和>>
运算符,评估顺序指定为从左到右。在C ++中,仍有许多地方没有指定评估顺序(甚至不存在,意味着评估可以交错),但是现在一些常见情况以可预测和可移植的方式运行,请参见此答案。
foo()
一定要在bar()
...之前被调用,并且他们编写的代码就像s << header() << body() << footer();
在中body()
计算使用的总和footer()
。对于函数参数,这种错误的发生频率较低。
setw
和setfill
它)。
它们不是按位运算符,在此上下文中称为插入和提取运算符。
http://www.cplusplus.com/doc/tutorial/basic_io/
这些仅用于视觉解释。如果研究开发自己的流和运算符重载,那么您甚至可以将+用作输入,将-用作输出:)
Bjarne选择它们是为了获得实际优先级,关联性和助记符的价值。
优先级并不完美,例如,布尔值和位级运算符很麻烦。
但这还可以。
插入运算符>>
和<<
分别与输入流和输出流一起使用,因为输入流意味着数据流进入程序,输出流意味着数据流出程序。由于这些插入运算符看起来像“方向”运算符(显示数据流的方向),因此>>
选择“输入”流和<<
“输出”流。
看一下代码部分...
int Num1;
cin >> Num1;
如果您仔细观察,>>
这里显示的是数据到变量的流(在程序中声明),这意味着数据到程序的流,这是Input流(这里cin
)的工作。
同样地cout
,
int Num2 = 5;
cout << Num2;
这里<<
显示了数据从程序中流出(作为程序的Num2
一部分),这是Output流的工作。
我希望所有这些对您都有意义。
{}
按钮缩进,也可以缩进四个空格。您也可以使用反引号(`)标记内联代码。
cout << "Output sentence"; // prints Output sentence on screen
cout << 120; // prints number 120 on screen
cout << x; // prints the content of x on screen
<<运算符将其后面的数据插入到其前面的流中。在上面的示例中,它将常量字符串Output句子,数字常量120和变量x插入到标准输出流cout中。
标准输入设备通常是键盘。通过对cin流应用重载的提取(>>)运算符,可以处理C ++中的标准输入。运算符之后必须是变量,该变量将存储将要从流中提取的数据。例如:
int age;
cin >> age;
我假设您知道C ++允许运算符重载。通常,仅在语义完全可转移的情况下才重载运算符(例如,重载向量类的加法以将两个向量加在一起)。我认为您的问题是关于为什么要使用位移位运算符,将它们重载到iostream并赋予它们与原始目的完全不同的含义。之所以可以这样做,是因为移位操作与iostream所做的工作相去甚远,所以没有人会误以为<<或>>正在对iostream进行移位。而且它们之所以方便使用的原因还在于它们的顺序是先评估左侧的操作数,然后评估右侧的操作数,然后进行操作。
但是,对于最初的问题,为什么呢?我真的不知道,在我看来,<<和>>很容易理解为从一个实体获取信息,然后将其放入另一个实体。为什么原因需要比这更复杂?使用它们似乎很明智,因为它们的含义很明显。您对操作员有什么更好的要求?
<<
和>>
不能保证。当人们编写s << foo() << bar()
并希望foo
被调用之前,这确实有时是bug的来源bar
。可以保证的结果foo
将在的结果之前发送到流,bar
但是不能保证计算顺序。只有,
,||
和&&
二进制运算符给出了这样的保证...并且该保证只有在不重载它们的情况下才存在。