======C++ 初探====== //第 1 章笔记// ---- ====HelloWorld==== ===函数=== * 函数:一段可以被反复调用的代码,包含: * 返回类型(''void'' 为不返回) * 函数名:用于调用 * 形参列表:表示函数接收的参数类型,可以为空,为 ''void'',可以无形参 * 函数体:具体的执行逻辑 // int 是返回类型 // main 后的括号是形参列表(为空) int main() { std::cout << "Hello World!" << std::endl; return 0; } // pInfo 是 parameter // test1, test2 是 argument void fun(const char* pInfo) { std::cout << pInfo << std::endl; } // 无形参的写法 // 通常是执行逻辑中不包含变量,但为了接口需要保留该变量的形参位置 // 因此只写形参类型 void fun2(const char* pInfo, int) { std::cout << pInfo << std::endl; } int main(int argc, char const *argv[]) { fun("test1"); fun2("test2", 1); return 0; } ===Main函数=== * ''main'' 是整个程序的入口,是操作系统调用 C++ 的接口 * 返回值为 ''int'', ''0'' 为正常返回。没有 ''return'' 默认 ''main'' 返回 ''0'' linux 下可以通过下面的命令检查程序的返回值(是否成功运行): #check the return type of the program $echo $? ==main 的形参列表== int main(int argc, char* argv[]) {} ===其他内容=== * 类型:C++ 引入的,用于赋予某段连续内存空间意义 * 语句:表明执行的操作 * 注释:单行,多行 ====系统 IO==== // 定义于 iostream 中 // 如果使用双引号,系统会在当前目录中找 // 如果使用三角括号,系统会优先找库中的内容 // 自定义 header 通常给 .h 后缀 #include #include "myheader.h" ===Iostream=== * 输入流:''cin'' * 输出流:''cout'' / ''cerr'' / ''clog'' * ''cerr'' 可以定向到不同的文件中,作为错误的输出 #cout 的内容会输出到 OutputText #cerr 的内容会输出到 ErrorText ./main > OutputText 2>ErrorText * ''clog'' 与 ''cerr'' 的区别在于是否立即刷新**缓冲区**: * ''cerr'' 输出的是错误信息,因此需要立即刷新缓冲区 * ''clog'' 输出的是日志信息,因此不会立即刷新缓冲区 * 手动刷新:''std::flush'' / ''std::endl'',但大量刷新存在性能问题,因此推荐只在必要的时候使用。 缓冲区是内存中的一个区域,用于优化读写的速度。缓冲区满了以后,会一次性将内容输出。但问题在于,程序没有正常结束时,缓冲区中的内容会丢失。如果为了查找程序的 Bug,那么这部分内容是需要保留的。这种情况下,需要立即刷新缓冲区。 ===命名空间=== 命名空间的存在是为了防止命名冲突。多人开发的过程中很可能会存在同名函数,放在一起可能会存在调用的冲突。这种情况下可以选择将其分置于不同的命名空间内: namespace NS1 { void fun() { std::cout << "NS1" << std::endl; } } namespace NS2 { void fun() { std::cout << "NS2" << std::endl; } } 没有标明命名空间的函数属于**全局空间**(//global space//): void fun() { std::cout << "global fun"; } 调用的方式有三种: * ''::'' 域解析符调用: // call int main(int argc, char const *argv[]) { NS1::fun(); NS2::fun(); } * ''using'' 调用 using namespace NS1; fun(); # output # 如果 NS1 中定义了 fun() NS1 # 如果 NS1 中没有定义 fun(), 全局中定义了 fun() global fun * 如果都定义了 ''fun()'',课程中说会先调用全局 ''fun()'',但测试发现 gcc 13.1.0 报错二义性。慎用 * ''using'' 会导致整个命名空间暴露给其他使用者,应当尽量使用域解析符。 * 名字空间别名:使用别名代替完整的命名空间名进行调用: namespace n = NS1; n::fun(); ==std 命名空间== * std 命名空间是 C++ 标准库的命名空间,用法与上述的命名空间用法相同。 * name mangling:C++ 会为不同命名空间下的相同 name 进行变化,为链接使用: # checking the mangling data nm main.o - o # demangling,查看 mangling 之前的原始数据 nm main.o - o | c++filt -t ''main()'' 不会做 mangling,因为 ''main()'' 是唯一的。 ====控制流==== * if statement:通过选择分支来选择执行的代码 * 条件部分:判断是否执行 * 使用**相等**(''=='')而不是**赋值** ''='' * 赋值表达式会被解释为 (y = 42 -> 42),而 42 会被转化为布尔值 ''true'',因此赋值表达式恒为真。 * 使用 ''const'' 阻止赋值表达式作为调价 * 语句部分:要执行的操作 * while statement:循环条件判断 ====结构体 / 自定义类型==== * 结构体:可以将不同的数据放置在一起,并使用 ''.'' 操作符访问内部元素 * 结构体可以作为参数被传入函数 * 结构体可以设置自己的成员函数 struct Point { int x = 1; int y = 2; //member function Point fun(Point p) { p.x += 1; p.y += 1; return p; } }; int main(int argc, char const *argv[]) { Point p; //call p = p.fun(p); std::cout << p.x << " " << p.y << std::endl; }