cpp学习-第八章-IO库

核心简记

IO类
头文件iostream:
-类型istream,wistream从流读取数据
-类型ostream,wostream向流写入数据
-类型iostream,wiostream读写数据
头文件fstream:
-类型ifstream,wifstream从文件读取数据
-类型ofstream,wofstream向文件中写入数据
-类型fstream,wfstream读写数据
头文件sstream:
-类型istringstream,wistringstream从string中读取数据
-类型ostringstream,wostringstream向string中写入数据
-类型stringstream,wstringstream读写数据

  1. w开头的为宽字符版本,操纵wchar_t类型。
  2. fstream与stringstream都继承于iostream。
  3. IO对象不可拷贝与赋值。

IO类共有

条件状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
strm::iostate
strm是一种IO类型。iostream是一种机器相关的整型提供了表达条件状态的完整功能
strm::badbit
strm::badbit用来指出流已崩溃
strm::failbit
strm::failbit用来指出一个IO操作失败了
strm::eofbit
strm::eofbit用来指出流达到了文件结束
strm::goodbit
strm::goodbit用来指出流未处于错误状态。此值保证为零
s.eof()
流 s 的 eofbit 置位,则返回 true
s.fail()
流 s 的 failbit 或 badbit 置位,则返回 true
s.bad()
流 s 的 badbit 置位,则返回 true
s.good()
若流 s 处于有效状态,则返回 true
s.clear()
将流 s 中的所有条件状态位复位,将流的状态设置为有效。返回void
s.clear(flag)
根据给定的 flags 标志位,将流 s 中对于条件状态位复位。 flag 的类型是strm::iostate。返回 void
s.setstate(flag)
根据给定的 flags 标志位,将流 s 中对于条件状态位置位。 flag 的类型是strm::iostate。返回 void
s.rdstate()
返回流 s 的当前条件,返回值类型为 strm::iostate

第一个是类型,之后四个为常量码,用于判断的。eof、bad都会影响fail。将流当条件等价于!fail()

每个输出流都有缓冲区,为了合成单一的系统调用。缓冲区刷新的原因:

  1. 程序正常结束
  2. 缓冲区满时
  3. 操作符如endl
  4. unitbuf设置每次刷新
  5. 读写被关联的流,关联的流将刷新。默认下cin与cerr关联cout

手动刷新:endl-换行后刷新。flush-直接刷新。ends-空格后刷新。
自动刷新:cout<< unitbuf (nounitbuf为复原) 之后自动刷新。
如果程序崩溃,不会刷新。

关联操作:
cin.tie(&关联的目标);
i与o可关联到o,只能关联一个,但可同时关联一个。

文件输入输出

fstream特有:
fstream a:创建一个未绑定的流。
fstream a(s):默认模式创建并打开文件,string与c式数组都可以。自动调用open
fstream a(s,mode):自定义模式
a.open(s) :打开s文件并绑定。可以带mode
a.close() :关闭文件,一个流想绑定另一个文件必须先关闭当前,再open。
a.is_open():判断是否可用

fstream对象销毁时,close会自动调用。一个{}内的对象结束时会自动销毁的。

文件模式:使用直接fstream类名::名就可以,是整数类型,可以|。
in:以读方式打开
out:以写方式打开
app:每次写为文件末尾-out才可
ate:打开后为文件末尾
trunc:截断文件
binary:二进制方式io

ate与binary模式可以用于任何类型文件流。out默认为trunc的(即打开的文件内容丢失)。想保留out的文件要用app

string流

stringstream特有:
stringstream a:创建未绑定的流对象。
stringstream a(s):创建保存s拷贝的流对象。
a.str()返回保存的string对象。
a.str(s)将s拷贝到a中。返回void 这个是覆盖

同样可以加mode

反汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
using std::ofstream;
using std::string;
int main(void)
{
ofstream fileout("123.txt",ofstream::out|ofstream::app);
string ls;
std::cin>>ls;
std::ostringstream strout(ls,std::ostringstream::app);
std::cin>>ls;
strout<<ls;
std::cout<<strout.str()<<std::endl;
fileout<<strout.str();
}

X86-64

指令简记

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
.text:0000000000008190 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000008190 main proc near ; DATA XREF: start+2E↑o
.text:0000000000008190
.text:0000000000008190 var_3E0 = qword ptr -3E0h
.text:0000000000008190 var_3D8 = qword ptr -3D8h
.text:0000000000008190 var_3D0 = qword ptr -3D0h
.text:0000000000008190 var_3C8 = qword ptr -3C8h
.text:0000000000008190 var_3C0 = qword ptr -3C0h
.text:0000000000008190 var_3B8 = qword ptr -3B8h
.text:0000000000008190 var_3B0 = qword ptr -3B0h
.text:0000000000008190 var_3A8 = qword ptr -3A8h
.text:0000000000008190 var_3A0 = qword ptr -3A0h
.text:0000000000008190 var_398 = qword ptr -398h
.text:0000000000008190 var_390 = qword ptr -390h
.text:0000000000008190 var_384 = dword ptr -384h
.text:0000000000008190 var_380 = byte ptr -380h
.text:0000000000008190 var_378 = byte ptr -378h
.text:0000000000008190 var_370 = byte ptr -370h
.text:0000000000008190 var_368 = byte ptr -368h
.text:0000000000008190 var_208 = byte ptr -208h
.text:0000000000008190 var_8 = qword ptr -8
.text:0000000000008190
.text:0000000000008190 ; __unwind {
.text:0000000000008190 push rbp
.text:0000000000008191 mov rbp, rsp
.text:0000000000008194 sub rsp, 3E0h
.text:000000000000819B mov rax, fs:28h
.text:00000000000081A4 mov [rbp+var_8], rax
//di与si or
.text:00000000000081A8 mov edi, 10h
.text:00000000000081AD mov ecx, 1
.text:00000000000081B2 mov esi, ecx
.text:00000000000081B4 mov [rbp+var_384], ecx
.text:00000000000081BA call sub_8360
//di为this var_390存指针 rsi为名 dx为mode
.text:00000000000081BF lea rsi, a123Txt ; "123.txt"
.text:00000000000081C6 lea rdx, [rbp+var_208]
.text:00000000000081CD mov rdi, rdx
.text:00000000000081D0 mov [rbp+var_390], rdx
.text:00000000000081D7 mov edx, eax
.text:00000000000081D9 call sub_30BD0
//初始ls var_398为指针
.text:00000000000081DE lea rsi, [rbp+var_370]
.text:00000000000081E5 mov rdi, rsi
.text:00000000000081E8 mov [rbp+var_398], rsi
.text:00000000000081EF call sub_31520
// std::cin>>ls;
.text:00000000000081F4 lea rsi, unk_5ED80
.text:00000000000081FB mov rdi, rsi
.text:00000000000081FE mov r8, [rbp+var_398]
.text:0000000000008205 mov [rbp+var_3A0], rsi
.text:000000000000820C mov rsi, r8
.text:000000000000820F call sub_8F40
//strout 的指针为var_3A8
.text:0000000000008214 lea rsi, [rbp+var_368]
.text:000000000000821B mov rdi, rsi
.text:000000000000821E mov r8, [rbp+var_398]
.text:0000000000008225 mov [rbp+var_3A8], rsi
.text:000000000000822C mov rsi, r8
.text:000000000000822F mov edx, [rbp+var_384]
.text:0000000000008235 mov [rbp+var_3B0], rax
.text:000000000000823C call sub_1DA30
// var_3A0是cin的指针 std::cin>>ls;
.text:0000000000008241 mov rdi, [rbp+var_3A0]
.text:0000000000008248 mov rsi, [rbp+var_398]
.text:000000000000824F call sub_8F40
// strout<<ls;
.text:0000000000008254 mov rdi, [rbp+var_3A8]
.text:000000000000825B mov rsi, [rbp+var_398]
.text:0000000000008262 mov [rbp+var_3B8], rax
.text:0000000000008269 call sub_1B8E0
//strout.str() rdi放返回的string对象位置 var_3C0为返回临时量的指针
.text:000000000000826E lea rsi, [rbp+var_378]
.text:0000000000008275 mov rdi, rsi
.text:0000000000008278 mov r8, [rbp+var_3A8]
.text:000000000000827F mov [rbp+var_3C0], rsi
.text:0000000000008286 mov rsi, r8
.text:0000000000008289 mov [rbp+var_3C8], rax
.text:0000000000008290 call sub_1DC00
//cout输出
.text:0000000000008295 lea rdi, unk_5EC40
.text:000000000000829C mov rsi, [rbp+var_3C0]
.text:00000000000082A3 call sub_1B8E0
//继续输出endl
.text:00000000000082A8 lea rsi, sub_1CBA0
.text:00000000000082AF mov rdi, rax
.text:00000000000082B2 call sub_1C8A0
// 析构临时量
.text:00000000000082B7 mov rdi, [rbp+var_3C0]
.text:00000000000082BE mov [rbp+var_3D0], rax
.text:00000000000082C5 call sub_31860
//str()
.text:00000000000082CA lea rax, [rbp+var_380]
.text:00000000000082D1 mov rdi, rax
.text:00000000000082D4 mov rsi, [rbp+var_3A8]
.text:00000000000082DB mov [rbp+var_3D8], rax
.text:00000000000082E2 call sub_1DC00
// fileout<<strout.str();
.text:00000000000082E7 mov rdi, [rbp+var_390]
.text:00000000000082EE mov rsi, [rbp+var_3D8]
.text:00000000000082F5 call sub_1B8E0
//析构临时量
.text:00000000000082FA mov rdi, [rbp+var_3D8]
.text:0000000000008301 mov [rbp+var_3E0], rax
.text:0000000000008308 call sub_31860
//strout析构
.text:000000000000830D mov rdi, [rbp+var_3A8]
.text:0000000000008314 call sub_1D5C0
//析构ls
.text:0000000000008319 mov rdi, [rbp+var_398]
.text:0000000000008320 call sub_31860
//析构fileout
.text:0000000000008325 mov rdi, [rbp+var_390]
.text:000000000000832C call sub_30220
//函数返回
.text:0000000000008331 mov rax, fs:28h
.text:000000000000833A mov rsi, [rbp+var_8]
.text:000000000000833E cmp rax, rsi
.text:0000000000008341 jnz loc_8352
.text:0000000000008347 xor eax, eax
.text:0000000000008349 add rsp, 3E0h
.text:0000000000008350 pop rbp
.text:0000000000008351 retn
.text:0000000000008352 ; ---------------------------------------------------------------------------
.text:0000000000008352
.text:0000000000008352 loc_8352: ; CODE XREF: main+1B1↑j
.text:0000000000008352 call ___stack_chk_fail
.text:0000000000008352 ; } // starts at 8190
.text:0000000000008352 main endp

寄存器都是被修改前保存的,函数调用并不保存通用寄存器,由调用方保护。返回的临时值也是要析构的(当返回的值不存时)。
对象操作都被编译为函数,如重载的运算符识别为先后传入左this与右this。返回的临时对象地址用di传入,和this冲突的话应该是先传返回地址,因为this算参数之中。
核心还是找this并确定类型。

ARM64

指令简记

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
.text:0000000000009560 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000009560 EXPORT main
.text:0000000000009560 main ; DATA XREF: LOAD:0000000000000E88↑o
.text:0000000000009560 ; .got:main_ptr↓o
.text:0000000000009560
.text:0000000000009560 var_3C8 = -0x3C8
.text:0000000000009560 var_3C0 = -0x3C0
.text:0000000000009560 var_3B8 = -0x3B8
.text:0000000000009560 var_3B0 = -0x3B0
.text:0000000000009560 var_3A8 = -0x3A8
.text:0000000000009560 var_3A0 = -0x3A0
.text:0000000000009560 var_394 = -0x394
.text:0000000000009560 var_390 = -0x390
.text:0000000000009560 var_388 = -0x388
.text:0000000000009560 var_380 = -0x380
.text:0000000000009560 var_378 = -0x378
.text:0000000000009560 var_218 = -0x218
.text:0000000000009560 var_18 = -0x18
.text:0000000000009560 var_10 = -0x10
.text:0000000000009560 var_s0 = 0
.text:0000000000009560
.text:0000000000009560 ; __unwind {
.text:0000000000009560 STR X28, [SP,#-0x10+var_10]!
.text:0000000000009564 STP X29, X30, [SP,#0x10+var_s0]
.text:0000000000009568 ADD X29, SP, #0x10
.text:000000000000956C SUB SP, SP, #0x3C0
.text:0000000000009570 MOV W0, #0x10
.text:0000000000009574 MOV W1, #1
.text:0000000000009578 MRS X8, #3, c13, c0, #2
.text:000000000000957C LDR X8, [X8,#0x28]
.text:0000000000009580 STUR X8, [X29,#var_18]
//w0 | w1
.text:0000000000009584 BL sub_96B8
//this为var_218
.text:0000000000009588 ADD X8, SP, #0x3D0+var_218
.text:000000000000958C ADRP X30, #a123Txt@PAGE ; "123.txt"
.text:0000000000009590 ADD X1, X30, #a123Txt@PAGEOFF ; "123.txt"
.text:0000000000009594 STR W0, [SP,#0x3D0+var_394]
.text:0000000000009598 MOV X0, X8
.text:000000000000959C LDR W2, [SP,#0x3D0+var_394]
.text:00000000000095A0 BL sub_2E3A4
//ls
.text:00000000000095A4 ADD X0, SP, #0x3D0+var_380
.text:00000000000095A8 BL sub_2EC18
// std::cin>>ls;
.text:00000000000095AC ADRP X8, #off_69F00@PAGE
.text:00000000000095B0 LDR X0, [X8,#off_69F00@PAGEOFF]
.text:00000000000095B4 ADD X1, SP, #0x3D0+var_380
.text:00000000000095B8 BL sub_A120
// 字串流this
.text:00000000000095BC ADD X8, SP, #0x3D0+var_378
.text:00000000000095C0 ADD X1, SP, #0x3D0+var_380
.text:00000000000095C4 MOV W2, #1
.text:00000000000095C8 STR X0, [SP,#0x3D0+var_3A0]
.text:00000000000095CC MOV X0, X8
.text:00000000000095D0 BL sub_1D144
//std::cin>>ls;
.text:00000000000095D4 ADRP X8, #off_69F00@PAGE
.text:00000000000095D8 LDR X0, [X8,#off_69F00@PAGEOFF]
.text:00000000000095DC ADD X1, SP, #0x3D0+var_380
.text:00000000000095E0 BL sub_A120
//strout<<ls; 先后传入左this与右this
.text:00000000000095E4 ADD X1, SP, #0x3D0+var_380
.text:00000000000095E8 ADD X8, SP, #0x3D0+var_378
.text:00000000000095EC STR X0, [SP,#0x3D0+var_3A8]
.text:00000000000095F0 MOV X0, X8
.text:00000000000095F4 BL sub_1AE9C
//strout.str() x8返回临时量
.text:00000000000095F8 ADD X8, SP, #0x3D0+var_388
.text:00000000000095FC ADD X1, SP, #0x3D0+var_378
.text:0000000000009600 STR X0, [SP,#0x3D0+var_3B0]
.text:0000000000009604 MOV X0, X1
.text:0000000000009608 BL sub_1D308
// std::cout<<strout.str()
.text:000000000000960C ADRP X8, #off_69C80@PAGE
.text:0000000000009610 LDR X0, [X8,#off_69C80@PAGEOFF]
.text:0000000000009614 ADD X1, SP, #0x3D0+var_388
.text:0000000000009618 BL sub_1AE9C
//endl
.text:000000000000961C ADRP X8, #off_69BE8@PAGE
.text:0000000000009620 LDR X1, [X8,#off_69BE8@PAGEOFF]
.text:0000000000009624 BL sub_1BD64
//析构临时量
.text:0000000000009628 ADD X8, SP, #0x3D0+var_388
.text:000000000000962C STR X0, [SP,#0x3D0+var_3B8]
.text:0000000000009630 MOV X0, X8
.text:0000000000009634 BL sub_2EFA8
//fileout<<strout.str();
.text:0000000000009638 ADD X8, SP, #0x3D0+var_218
.text:000000000000963C ADD X0, SP, #0x3D0+var_390
.text:0000000000009640 ADD X1, SP, #0x3D0+var_378
.text:0000000000009644 STR X8, [SP,#0x3D0+var_3C0]
.text:0000000000009648 MOV X8, X0
.text:000000000000964C MOV X0, X1
.text:0000000000009650 BL sub_1D308
.text:0000000000009654 ADD X1, SP, #0x3D0+var_390
.text:0000000000009658 LDR X0, [SP,#0x3D0+var_3C0]
.text:000000000000965C BL sub_1AE9C
.text:0000000000009660 ADD X8, SP, #0x3D0+var_390
.text:0000000000009664 STR X0, [SP,#0x3D0+var_3C8]
.text:0000000000009668 MOV X0, X8
.text:000000000000966C BL sub_2EFA8
//析构三个量
.text:0000000000009670 ADD X0, SP, #0x3D0+var_378
.text:0000000000009674 BL sub_1CC54
.text:0000000000009678 ADD X0, SP, #0x3D0+var_380
.text:000000000000967C BL sub_2EFA8
.text:0000000000009680 ADD X0, SP, #0x3D0+var_218
.text:0000000000009684 BL sub_2D990
.text:0000000000009688 MRS X8, #3, c13, c0, #2
.text:000000000000968C LDR X8, [X8,#0x28]
.text:0000000000009690 LDUR X0, [X29,#var_18]
.text:0000000000009694 CMP X8, X0
.text:0000000000009698 B.NE loc_96B4
.text:000000000000969C MOV W8, WZR
.text:00000000000096A0 MOV W0, W8
.text:00000000000096A4 ADD SP, SP, #0x3C0
.text:00000000000096A8 LDP X29, X30, [SP,#0x10+var_s0]
.text:00000000000096AC LDR X28, [SP+0x10+var_10],#0x20
.text:00000000000096B0 RET
.text:00000000000096B4 ; ---------------------------------------------------------------------------
.text:00000000000096B4
.text:00000000000096B4 loc_96B4 ; CODE XREF: main+138↑j
.text:00000000000096B4 BL .__stack_chk_fail
.text:00000000000096B4 ; } // starts at 9560
.text:00000000000096B4 ; End of function main

注意返回值临时量不拷贝构造时会立刻析构,因为做为临时量其只用于函数返回,函数调用结束、返回值使用后就不应该存在了,当仅作为临时量时需要立刻析构。