istream对象——源码剖析
省流:istream对象只能接收左值,不能接收右值
1 先看看cin的使用
我们知道,cin可以接收一个对象,然后存入到对应的变量里面
例如
int a;
cin >> a;
cout << a;
如果我们输入的是10,那就会输出10(狗头:这不是废话嘛)
2 思考:能不能直接给cin一个字面值?
cin >> 10;输入一个10?答案是不能的。
示例代码
int main(int argc, char** argv)
{
/* 下面这条语句将会产生非常多的报错:
error: no match for ‘operator>>’ (operand types are ‘std::istream’ {aka ‘std::basic_istream<char>’} and ‘int’)
error: invalid conversion from ‘int’ to ‘std::basic_istream<char>::__istream_type& (*)(std::basic_istream<char>::__istream_type&)’ {aka ‘std::basic_istream<char>& (*)(std::basic_istream<char>&)’} [-fpermissive]
error: invalid conversion from ‘int’ to ‘std::basic_istream<char>::__ios_type& (*)(std::basic_istream<char>::__ios_type&)’ {aka ‘std::basic_ios<char>& (*)(std::basic_ios<char>&)’} [-fpermissive]
error: invalid conversion from ‘int’ to ‘std::ios_base& (*)(std::ios_base&)’ [-fpermissive]
error: cannot bind non-const lvalue reference of type ‘bool&’ to an rvalue of type ‘bool’
...还有很多
*/
cin >> 10;//error
return 0;
}
那为什么会报错呢?
我们先从第一条报错开始看(notify:一般来说遇到很多报错的时候,都是从最开始的那个报错开始看)
error: no match for ‘operator>>’ (operand types are ‘std::istream’ {aka ‘std::basic_istream<char>’} and ‘int’)
上面这条报错的含义:
没有匹配' operator>> '(操作数类型为' std::istream '{也称为' std::basic_istream<char> '}和' int ')
楼主英文比较蹩脚,就直接有道翻译了。乍一看有点难搞懂是啥意思,我再翻译一下(也不知道对不对,不对的话麻烦您告诉我怎么理解。谢谢)
没有找到匹配的 操作对象是std::istream(也称为std::basic_istream<char>)和int 的 重载>>操作符的函数
嘻嘻,有点眉目了,它说没有重载>>的函数与我们传入的参数匹配,那我们就去看看cin重载了哪些>>函数。
查看了cin的源码,cin是一个istream对象,而istream是一个别名而已,真正的类型是一个basic_istream模板类。
extern istream cin;
typedef basic_istream<char, char_traits<char>> istream;
而这个basic_istream模板类重载了>>,所有重载函数如下:
basic_istream::operator>>
重载的函数
basic_istream& operator>>(basic_istream& (* Pfn)(basic_istream&));
basic_istr eam& operator>>(ios_base& (* Pfn)(ios_base&));
basic_istream& operator>>(basic_ios<Char_T, Tr>& (* Pfn)(basic_ios<Char_T, Tr>&));
basic_istream& operator>>(basic_streambuf<Char_T, Tr>* strbuf);
basic_istream& operator>>(bool& val);
basic_istream& operator>>(short& val);
basic_istream& operator>>(unsigned short& val);
basic_istream& operator>>(int& val);
basic_istream& operator>>(unsigned int& val);
basic_istream& operator>>(long& val);
basic_istream& operator>>(unsigned long& val);
basic_istream& operator>>(long long& val);
basic_istream& operator>>(unsigned long long& val);
basic_istream& operator>>(void *& val);
basic_istream& operator>>(float& val);
basic_istream& operator>>(double& val);
basic_istream& operator>>(long double& val);
得出结论:由以上源码可知,istream对象只能接收左值(引用作为形参的函数,实参只能是左值,因为右值无法取其引用)
为了验证上述结论:再举个例子
目标:将Person的数据读入到isatream对象里面
#include<iostream>
using std::cin;
using std::cout;
using std::istream;
using std::string;
/*class Person start*/
class Person {
public:
Person() {
cout << "Person, The default constructor is called " << endl;
}
Person(string name, string addr, unsigned age)
:m_strName(name), m_strAddress(addr), m_unAge(age) {
cout << "Person, The constructor is called " << endl;
}
~Person() {
cout << "~Person, The desstructor is called " << endl;
}
void setName(string name) {
m_strName = name;
}
void setAddress(string addr) {
m_strAddress = addr;
}
void setAge(unsigned age) {
m_unAge = age;
}
string getName() const {
return m_strName;
}
string getAddress() const {
return m_strAddress;
}
unsigned getAge() const {
return m_unAge;
}
private:
string m_strName;
string m_strAddress;
unsigned m_unAge{0};
};/*class Person end*/
istream& readPerson(istream& is, Person& p)
{
//is >> p.getName() >> p.getAddress() >> p.getAge();//error
string name = p.getName();
string addr = p.getAddress();
unsigned age = p.getAge();
is >> name >> addr >> age;
return is;
}
注意了:
is >> p.getName() >> p.getAddress() >> p.getAge();//error
这个代码会报错,错误与上面的报错类似,有兴趣的朋友可自行验证一下。
3 结束语
到此,我们总算知道了为什么>>不能传入右值了。
如果文章对您有帮助,劳烦一键三连加关注哦。
初来乍到,如果文章内容有错误的地方或者有关于文章排版的建议、意见,麻烦留言指出。十分感谢