c语言中define和const(std::cinstd::coutstd::cerr和std::endl在C)

在C 里std::cin、std::cout、std::cerr和std::endl分别是标准输入、标准输出、标准错误输出和刷新缓冲区并换行,它们都在命名空间std中,那么它们真实面目是什么?我们先来看一段代码:,下面我们就来说一说关于c语言中define和const?我们一起去了解并探讨一下这个问题吧!

c语言中define和const(std::cinstd::coutstd::cerr和std::endl在C)

c语言中define和const

C 输入和输出

在C 里std::cin、std::cout、std::cerr和std::endl分别是标准输入、标准输出、标准错误输出和刷新缓冲区并换行,它们都在命名空间std中,那么它们真实面目是什么?我们先来看一段代码:

#include <iostream> int main() { std::cout << "Hello world!" << std::endl; std::cerr << "error" << std::endl; return 0; }

这段代码很简单,就是输出"Hello world!"和"error",那么这段代码的底层原理是?我们先来看一下std::cout在标准库中的定义:

#ifndef _LIBCPP_HAS_NO_STDOUT extern _LIBCPP_FUNC_VIS ostream cout; extern _LIBCPP_FUNC_VIS wostream wcout; #endif ...... typedef basic_streambuf<char> streambuf; typedef basic_istream<char> istream; typedef basic_ostream<char> ostream; typedef basic_iostream<char> iostream; ...... template <class _CharT, class _Traits> class _LIBCPP_TEMPLATE_VIS basic_ostream : virtual public basic_ios<_CharT, _Traits> { ...... };

从以上代码我们可以看出std::cout是一个类basic_stream<char>的一个实例,那么很容易我们就能想到<<很有可能是类basic_stream<char>的一个成员函数,继续追踪下去,看看<<到底是啥。在类模板basic_stream中我们找到成员函数声明如下:

basic_ostream& operator<<(bool __n); basic_ostream& operator<<(short __n); basic_ostream& operator<<(unsigned short __n); basic_ostream& operator<<(int __n); basic_ostream& operator<<(unsigned int __n); basic_ostream& operator<<(long __n); basic_ostream& operator<<(unsigned long __n); basic_ostream& operator<<(long long __n); basic_ostream& operator<<(unsigned long long __n); basic_ostream& operator<<(float __f); basic_ostream& operator<<(double __f); basic_ostream& operator<<(long double __f); basic_ostream& operator<<(const void* __p); basic_ostream& operator<<(basic_streambuf<char_type, traits_type>* __sb);

充分证实了我们猜想,<<其实是成员函数operator<<并且返回值是basic_ostream&,到这里我们就可以看出std::cout << "Hello World!"其实是basic_ostream实例变量cout调用成员函数operator<<输出字符串"Hello World!"并返回basic_ostream&。

那么std::endl是不是某个类的实例呢?我们看看std::endl在标准库的定义:

template <class _CharT, class _Traits> inline _LIBCPP_INLINE_VISIBILITY basic_ostream<_CharT, _Traits>& endl(basic_ostream<_CharT, _Traits>& __os) { __os.put(__os.widen('\n')); __os.flush(); return __os; }

从代码里可以看出,std::endl其实是一个函数模板,调用该函数会将一个换行符"\n"放入缓冲区,并刷新缓冲区,最后返回basic_ostream&。到这里我们终于明白std::cout << "Hello World!" << std::endl;的含义了,basic_ostream实例变量cout调用成员函数operator<<输出字符串"Hello World!",返回basic_ostream&并继续调用成员函数operator<<输出换行符并刷新输出缓冲区。

现在我们很容易想到std::cerr和std::cout应该差不多,区别则是std::cerr是标准错误输出,将信息输出到标准错误流。std::cerr定义如下:

extern _LIBCPP_FUNC_VIS ostream cerr; extern _LIBCPP_FUNC_VIS wostream wcerr; extern _LIBCPP_FUNC_VIS ostream clog; extern _LIBCPP_FUNC_VIS wostream wclog;

最后我们看看std::cin到底是什么玩意,先来看下下面这段代码:

#include <iostream> int main() { std::string name; std::cin >> name; return 0; }

代码很简单,就是想通过标准输入输入名字,并保存在变量name中。有了上面的经验,我们很容易想到std::cin应该是某个类的实例变量,而>>则是类的成员函数。std::cin的定义如下:

#ifndef _LIBCPP_HAS_NO_STDIN extern _LIBCPP_FUNC_VIS istream cin; extern _LIBCPP_FUNC_VIS wistream wcin; #endif ...... typedef basic_streambuf<char> streambuf; typedef basic_istream<char> istream; typedef basic_ostream<char> ostream; typedef basic_iostream<char> iostream; ...... template <class _CharT, class _Traits> class _LIBCPP_TEMPLATE_VIS basic_istream : virtual public basic_ios<_CharT, _Traits> { ...... };

从代码中可以看出std::cin是类basic_istream<char>的实例变量,且basic_istream是类模板。下面我们看看>>在basic_istream中声明:

basic_istream& operator>>(basic_streambuf<char_type, traits_type>* __sb); basic_istream& operator>>(bool& __n); basic_istream& operator>>(short& __n); basic_istream& operator>>(unsigned short& __n); basic_istream& operator>>(int& __n); basic_istream& operator>>(unsigned int& __n); basic_istream& operator>>(long& __n); basic_istream& operator>>(unsigned long& __n); basic_istream& operator>>(long long& __n); basic_istream& operator>>(unsigned long long& __n); basic_istream& operator>>(float& __f); basic_istream& operator>>(double& __f); basic_istream& operator>>(long double& __f); basic_istream& operator>>(void*& __p);

不出我们所料>>确实是成员函数operator>>并返回basic_istream&,那么这段代码std::cin>>name就很容易理解了,basic_istream<char>类实例变量cin调用成员函数operator>>从标准输入输入数据,并保存在变量name中。

到这里std::cout、std::cin、std::cerr和std::endl的含义终于真相大白了!

往期推荐

C 11很吊的新特性!std::function

C 里std::enable_shared_from_this是干什么用的?

C mutable关键字如何使用?

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页