As an interesting tidbit, sed uses a temp file as well (this just does it for you):
$ strace sed -i 's/foo/bar/g' foo
open("foo", O_RDONLY|O_LARGEFILE) = 3
...
open("./sedPmPv9z", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 4
...
read(3, "foo\n"..., 4096) = 4
write(4, "bar\n"..., 4) = 4
read(3, ""..., 4096) = 0
close(3) = 0
close(4) = 0
rename("./sedPmPv9z", "foo") = 0
close(1) = 0
close(2) = 0
Description:
The tempfile ./sedPmPv9z
becomes fd 4, and the foo
files becomes fd 3. The read operations are on fd 3, and the writes on fd 4 (the temp file). The foo file is then overwritten with the temp file in the rename call.