不,没有。但让我们看看名为cin.ignore() 的幕后发生了什么。让我们以llvm libcxx sources 为例,我发现它们比 gcc 的浏览速度更快。
extern istream cin; 在 iostream 中,但它在 iostream.cpp 中的应用程序启动时使用静态分配的缓冲区和从良好的“旧”FILE *stdin 构造的 __stdoutbuf 对象进行初始化:
_ALIGNAS_TYPE (istream) char cin [sizeof(istream)];
ios_base::Init::Init() {
istream* cin_ptr = ::new(cin) istream(::new(__cin) __stdinbuf <char>(stdin) );
...
istream::ignore() 函数可以在istraem 中找到。这很简单,首先我们检查用户是想清除流中的所有字符还是只清除其中的一部分(if (__n == numeric_limits<streamsize>::max()))。然后函数在循环中调用this->rdbuf()->sbumpc() 预定义的计数数量(或无限循环,以防__n 等于numeric_limits<steramsize::max())。我们可以从cppreference找到sbumpc()成为std::basic_streambuf的成员:
int_type sbumpc();
Reads one character and advances the input sequence by one character.
If the input sequence read position is not available, returns uflow(). Otherwise returns Traits::to_int_type(*gptr()).
所以我们可以简单地推断出this->rdbuf() 将句柄返回到__stdinbuf<char>(stdin)。在cin::ignore 函数中,对__stdinbuf<char>(stdin)::sbumpc() 的调用被多次调用,我们想忽略多少个字符。所以让我们去sbumpc()!先来看看streambuf:
int_type sbumpc() {
if (__ninp_ == __einp_)
return uflow();
return traits_type::to_int_type(*__ninp_++);
}
所以if (__ninp_ == __einp_) 正在streambuf 对象中进行一些内部缓冲,如果我们的缓冲区中已经存在缓冲字符,则不要调用uflow()。 __ninp__ 指针在每次读取后递增,一定是这样。 uflow() 被__stdinbuf : public basic_streambuf< .... > 重载,来自__std_stream:
template <class _CharT>
typename __stdinbuf<_CharT>::int_type
__stdinbuf<_CharT>::uflow()
{
return __getchar(true);
}
噗,我们去__getchar看看true参数是什么。它就在__std_stream 的正下方。
这是一个长函数,具有主要功能,负责一些缓冲。但是我们可以立即发现这个函数的核心:
template <class _CharT>
typename __stdinbuf<_CharT>::int_type
__stdinbuf<_CharT>::__getchar(bool __consume) {
....
int __c = getc(__file_);
if (__c == EOF)
return traits_type::eof();
...
}
让我们从头开始:
-
cin 是一个 istraem 对象,从 __stdinbuf<char>(stdin) 初始化
-
istream::ignore() 调用 basic_streambuf::sbumpc() 预定义的次数,可能在使用 stdin 初始化的对象上
-
basic_streambuf::sbumpc() 负责一些缓冲,如果缓冲区为空,则调用 basic_streambuf::uflow()。
-
basic_streambuf::uflow() 被__stdinbuf::uflos() 重载并调用__stdinbuf::__getchar()
-
__sinbuf::__getchar() 调用 getc(__file__) 所以可能 getc(stdin) 从流中读取一个字符
总结一下:
void stdin_ignore(size_t n, int delim)
{
while (n--) {
const int c = getc(stdin);
if (c == EOF)
break;
if (delim != EOF && delim == c) {
break;
}
}