I'm using a Standard iostream to get some input from a file, and I'm confused about unget()
versus putback(character)
. It seems to me from the documentation that these functions are effectively identical, where unget()
just remembers the character put in, so I'm nervous. I've always used putback(character)
, but character
is always the last read character and I've been thinking about changing to unget()
. Is putback(character)
always identical to unget()
, if character
is always the last read character?

- 378,754
- 76
- 643
- 1,055

- 144,682
- 38
- 256
- 465
2 Answers
You can't lie with unget()
. It "ungets" the last-read character. You can lie with putback(c)
. You can "putback" some character other than the last-read character. Sometimes putting back a character other than the last-read character can be useful.
Also, if the underlying read buffer really does have buffering capability, you can "putback" more than one character. I think ungetc()
is limited to one character.
Edit
Nope. It looks like unget()
can go as far back as putback()
.

- 32,454
- 9
- 60
- 108
-
Not that I'm complaining about your perfectly reasonable answer, but I don't think it actually answers the question. If I replace all my `putback(character)` calls (where `character` is guaranteed to be the last read character) with `unget()`, is the defined behaviour identical? – Puppy Jul 20 '11 at 23:24
-
2It sure looks that way to me. `putback()` gives you the ability to put something back other than the last-read character. If you only use `putback(last_read_character)` the effect is the same as calling `unget()`, but without the explicit guarantee that you truly are "ungetting" the last-read character. – David Hammen Jul 20 '11 at 23:41
-
I ended up using a custom stream anyway that can put back as many characters as necessary. – Puppy Jul 21 '11 at 12:31
It's not the answer you probably expect, but want to introduce my reasoning. Documentation stays that the methods putback
and unget
call streambuf::sputbackc
and streambuf::sungetc
respectively. Definitions are as follow:
streambuf::sungetc
Moves the get pointer one character backwards, making the last character gotten by an input operation available once again for the next input operation.
During its operation, the function will call the protected virtual member function pbackfail if the get pointer gptr points to the same position as the beginning pointer eback.
The other one:
streambuf::sputbackc
The get pointer is moved back to point to the character right before its current position so the last character gotten, c, becomes available again as the character to be read at that position by the next input operation.
During its operation, the function calls the protected virtual member function pbackfail either if the character c doesn't match gptr()[-1] or if the get pointer gptr points to the same position as the beginning pointer eback.
When c does not match the character at that position, the default definition of pbackfail in streambuf will prepend c to be the character extracted at that position if possible, but derived classes may override this behavior.
The member function sungetc behaves in a similar way but without taking any parameter
As sputbackc
calls pbackfail
if character doesn't match, it means the method has to check if the values are equal. It looks like the additional check is the only overhead, but have no idea how it is solved in practise. I can imagine that if the last character is not stored in the object then it has to be reread, so you might expect it even when the characters are guaranteed to be the same.
I was a little bit concerned about situation when we call unget
, but last character is not available. Would the putback
put the value correctly? I doubt, but it shouldn't be the case while operating on files.

- 12,574
- 4
- 43
- 54
-
1It looks like there's more than one difference. Putback looks like it prepends? Are you sure it doesn't replace. Consider input "ABC", if you read A, then B, then putback B, prepending would insert and make the input stream "ABBC". Is this true? – Lee Louviere Aug 02 '11 at 16:11
-
1@Xaade, it's up to implementation, `streambuf` does nothing by default. `stringbuf` replaces character in original string (if has write privileges), but `filebuf` replaces the character in internal buffer only, so underlying file is not affected (but also decrements get pointer, so there is no effect of inserting new character into stream). More details in spec: http://www.cplusplus.com/reference/iostream/streambuf/pbackfail/. – tomasz Aug 02 '11 at 23:03