【C++】 入门基础(第一版)
目录1.C 的发展历史简单了解即可1.1 C 的诞生与早期发展1979-19851.2 标准化进程与C981989-19981.3 C03与TR12003-20051.4 现代CC11/14/17/202011至今1.5 未来展望C23及以后2. C 的第一个程序3.命名空间3.1 namespace 的价值3.2 namespace 的定义3.3 命名空间使用 using4. C 的输出与输入函数 cout、endl、cin5. 缺省参数6. 函数重载7. 引用7.1 引用的概念和定义7.2 引用的特性7.3 引用的使用7.4 const 与引用7.5 指针于引用的关系8. inline9. nullptr1.C 的发展历史简单了解即可C的起源可以追溯到1979年当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普这个翻译的名字不 同的地⽅可能有差异)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复杂的软件开 发任务特别是模拟和操作系统的开发⼯作他感受到了现有语⾔如C语⾔在表达能⼒、可维护性 和可扩展性⽅⾯的不⾜。1983年Bjarne Stroustrup在C语⾔的基础上添加了⾯向对象编程的特性设计出了C语⾔的雏形 此时的C已经有了类、封装、继承等核⼼概念为后来的⾯向对象编程奠定了基础。这⼀年该语⾔被正式命名为C。在随后的⼏年中C在学术界和⼯业界的应⽤逐渐增多。⼀些⼤学和研究所开始将C作为教学和研 究的⾸选语⾔⽽⼀些公司也开始在产品开发中尝试使⽤C。这⼀时期C的标准库和模板等特性也得到了进⼀步的完善和发展。C的标准化⼯作于1989年开始并成⽴了⼀个ANSI和ISOInternational Standards Organization国际标准化组织的联合标准化委员会。1994年标准化委员会提出了第⼀个标准化草 案。在该草案中委员会在保持斯特劳斯特卢普最初定义的所有特征的同时还增加了部分新征。在完成C标准化的第⼀个草案后不久STLStandard Template Library是惠普实验室开发的⼀系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室⼯作时所开发出来的。在通过了标准化第⼀个草案之后联合标准化委员会投票并通过了将STL包含到C标准中的提议。STL对C的扩展超出C的最初定义范围。虽然在标准中增加STL是个很重要的决定但也因此延缓了C标准化的进程。1997年11⽉14⽇联合标准化委员会通过了该标准的最终草案。1998年C的ANSI/IS0标准被投⼊使⽤。1.1 C 的诞生与早期发展1979-19851979年Bjarne Stroustrup在贝尔实验室开始开发一种名为“C with Classes”的语言旨在为C语言增加面向对象编程的特性。这一时期的C主要关注类、封装、继承等核心概念为后来的面向对象编程奠定了基础。1983年该语言正式更名为C其中“”是C语言中的自增运算符象征着对C语言的改进和扩展。同年第一个C编译器Cfront发布它能够将C代码转换为C代码然后使用C编译器进行编译。1.2 标准化进程与C981989-19981989年ANSI和ISO联合成立了C标准化委员会开始制定C语言标准。经过多年的讨论和修订第一个国际标准C98于1998年正式发布。C98标准引入了标准模板库STL这是一个包含容器、算法和迭代器的强大库极大地提高了C的编程效率和代码复用性。STL的加入使得C成为一门真正支持泛型编程的语言。1.3 C03与TR12003-20052003年ISO发布了C03标准这主要是对C98的一个技术修正版本修复了一些已知问题但没有引入重要的新特性。2005年技术报告TR1Technical Report 1发布为C标准库引入了许多新组件如智能指针、正则表达式库、随机数生成器等这些特性后来被纳入C11标准。1.4 现代CC11/14/17/202011至今C112011被称为“现代C”的开端引入了自动类型推导auto、范围for循环、lambda表达式、右值引用、移动语义、智能指针unique_ptr、shared_ptr、并发支持等革命性特性。C142014作为C11的小幅更新主要完善了C11的特性如泛型lambda、变量模板、二进制字面量等。C172017引入了结构化绑定、if constexpr、折叠表达式、文件系统库等特性进一步简化了现代C编程。C202020引入了概念Concepts、协程Coroutines、范围Ranges、模块Modules等重大特性标志着C进入了新的发展阶段。1.5 未来展望C23及以后C23标准正在制定中预计将引入更多改进和新特性。C标准委员会继续致力于提高语言的安全性、性能和易用性同时保持与现有代码的兼容性。从最初的“C with Classes”到现在的现代C这门语言已经走过了40多年的发展历程。它不断适应新的编程范式和技术需求在系统编程、游戏开发、高性能计算、嵌入式系统等领域仍然保持着强大的生命力。2. C 的第一个程序在学习C语言输出都是以printf 来进行经行输出操作的//test.cpp #inclulde stdio.h int main() { printf(hello world\n); return 0; }但在C程序里更多都会使用iostream库函数内的cout endl//test.cpp #include iostream using namespace std; int main() { cout hello world\n endl; return 0; }3.命名空间3.1 namespace 的价值在C语言程序中在编程的时候会出现一些声明类型的同名报错的情况在大型的程序中出现同名的情况会更多。#include stdio.h #include stdlib.h int rand 10; int main() { printf(%d,rand); return 0; }所有为了防止出现类型的同名等情况c系统引入namespace 就是为了更好的解决这样的问题。3.2 namespace 的定义定义命名空间需要使用到namespace 关键字后面跟命名空间名字让后接{}{}中就是命名空间的成员命名空间中就可以定义变量/函数等等。namespace 本质是定义出一个域这样的域互不影响不同的域可以定义相同名字的变量。C中域有函数局部域全局域命名空间域类域域影响的是编译时语法查找⼀个变量/函数/ 类型出处(声明或定义)的逻辑所有有了域隔离名字冲突就解决了。局部域和全局域除了会影响 编译查找逻辑还会影响变量的⽣命周期命名空间域和类域不影响变量⽣命周期。namespace 只能定义在全局也可以嵌套。大型项目多个文件多定义相同的命名空间编译器只会认为是一个命名空间不会影响。C 的标准库都放置在一个std (standdard)的命名空间中。#include stdio.h #include stdlib.h namespace a { int rand 10; int Add(int a,int b) { return a b; } } int main() { printf(%d\n,rand); printf(%d\n,a::rand); printf(%d\n,a::Add(10,2)); return 0; }3.3 命名空间使用 using一般命名空间的内容不能被直接使用到会默认在全局进行寻找命名空间内的内容是不会主动寻找的在一些代码中就会报错。使用命名空间的变量/函数 有三种方式1使用“::”指定命名空间访问项目推荐这种方式最安全2使用using 将命名空间的某个成员经行张开容易报错比较不安全3使用using 将命名空间全部张开推荐日常写代码项目最不可以使用的最不安全#include iostream using namespace std; namespace pit { int a10; int b20; } //张开部分命名空间 using pit::a; int main() { cout a endl; return 0; } //张开整个命名空间 using namespace pit; int main() { cout a b endl; return 0; }4. C 的输出与输入函数 cout、endl、ciniostream 库简介iostream 是 C 标准库中用于处理输入输出的头文件其名称是Input Output Stream的缩写。它定义了标准的输入、输出流对象是 C 进行控制台 I/O 操作的基础。主要包含以下三个预定义对象std::cout标准输出流对象通常关联到控制台屏幕用于输出数据。std::cin标准输入流对象通常关联到键盘用于从控制台读取数据。std::endl输出换行符并刷新输出缓冲区。基本用法示例#include iostream int main() { int age; std::string name; // 使用 cout 输出提示信息 std::cout 请输入您的姓名: ; // 使用 cin 读取用户输入的字符串 std::cin name; std::cout 请输入您的年龄: ; std::cin age; // 使用 cout 输出结果endl 用于换行 std::cout 您好 name 您今年 age 岁。 std::endl; return 0; }注意事项使用std::cout和std::cin时通常需要包含iostream头文件。为了简化代码可以使用using namespace std;来省略std::前缀但在大型项目中不建议这样做以避免命名冲突。std::endl不仅输出换行还会刷新缓冲区这在需要立即显示输出时很有用但频繁使用可能影响性能。对于简单的换行也可以使用转义字符\n如std::cout Hello\n;。与 C 语言 printf/scanf 的区别C 的cout/cin是类型安全的编译器会在编译时检查类型是否匹配而 C 语言的printf/scanf依赖于格式字符串类型不匹配可能导致运行时错误。总结iostream库函数的输出与输入方式比stdio.h更加灵活。5. 缺省参数缺省参数就是函数在没有传参的时候可以进行提前预设好的默认值进行。#include iostream using namespace std; int fun(int a 10,int b 20) { return a b; } int main() { cout fun() endl; return 0; }可以看到函数fun 并没有进行传参但代码依然执行没有传参的内容会用默认的数值代替有参数就优先用传参内容但不能像 fun(,40) 的操作带缺省的函数调用C 规定必须从左到右一次给实参不能跳跃传给实参。全缺省就是全部形参给缺省值半缺省就是部分形参给缺省值。C规定半缺省参数必须从右往左依次连续缺省不能间隔跳跃给缺省值。建议在需要写入缺省参数和非缺省参数的函数中缺省参数都统一在最右边。函数声明和定义分离时缺省参数不能在函数声明和定义中同时出现规定必须函数声明给缺省值。// .h 声明 void func(int a 10); // .cpp 定义形参不带默认值 void func(int a) { cout a; }6. 函数重载在C 中可以支持在相同的域多个相同名字的函数前提是函数传参不相同参数类型不同参数数量不同参数顺序不同但尽量不要使用缺省参数要使用要确保不会出现函数雷同的情况。正常情况int Add(int left, int right); double Add(double left, double right); void f(); void f(int a); void f(int a, char b); void f(char b, int a);报错情况void fun() { //... } void fun(int a10) { //... } // 返回值不同不能作为重载条件因为调⽤时也⽆法区分 //void fxx() //{} // //int fxx() //{ // return 0; //}7. 引用7.1 引用的概念和定义引用类似指针但不是指针功能类似给变量改名字编译器不会开辟空间会与原来的变量的空间共享空间所有变量内容更改就会一起更改内容。类型 引用别名引用对象引用的功能只是在为了防止引入太多的运算符而被发明的。#include iostream using namespace std; int main() { int a 10; int A a; int AA a; cout a endl; cout A endl; AA--; cout a endl; cout A endl; cout AA endl; return 0; }7.2 引用的特性引用一定需要初始化一个变量可以有多个引用引用一旦被初始化就本办法更改7.3 引用的使用C 引用多用于传参、作返回值减少拷贝提效修改引用会同步修改原对象。引用传参和指针传参作用相近引用书写更简便。引用返回值场景复杂后续面向对象章节再细讲。引用与指针功能部分重叠、各有优势无法完全替代C 引用一经定义不能更换绑定对象和 Java 引用有本质区别。部分数据结构教材会用 C 引用代替 C 指针简化代码没学过引用容易看不懂。#include iostream using namespace std; void Swap(int a, int b) { int tmp a; a b; b tmp; } int main() { int a 10; int b 20; Swap(a, b); cout a endl; cout b endl; return 0; }7.4 const 与引用回顾const 可以让对象内容不可可以改变就是一个限制防止进行更改。引用要引用一个const 的对象就需要用const 进行应用const 引用也可以引用普遍对象因为对象的访问权限只能缩小不能放大。可以不需要注意类型int rb 3*a;double d13.32;int rbb;这些一下场景下次a*3的和结果存在在一个临时变中的这些临时变量在C中都具有常性就是类似常量一样例如8这个常量没办法改变8的大小8就是8所以这里就触发权限放大必须使用const的常引用才可以。临时对象编译器为存放表达式结果创建的无名对象。7.5 指针于引用的关系指针与引用功能重叠、各有特性无法互相替代引用是变量别名不额外开辟内存指针存地址单独占用空间。引用定义时必须初始化指针语法允许不初始化。引用绑定对象后无法更换指针可随意修改指向。引用直接访问原变量指针需解引用访问。sizeof引用得到原变量大小指针固定为 4/8 字节32/64 位。指针易产生空、野指针引用使用更安全。8. inline每次函数的调用都需要计算机都需要开辟空间调用太多就会导致计算机内存不足的情况而inline 类似define 的功能把对于的内容在编译的时虽然运行内存下降但这样会导致原本的代码行数成几何倍数的增加到这这个项目的大小变大所以inline 只适合个给一些短小的函数使用。inline int add(int a, int b) { return a b; } int main() { int a 10; int b 20; int c add(a, b); cout c endl; return 0; }9. nullptrNULL 实际ishi一个宏。在传统的C头文件stddef.h)中可以看到代码#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endifNULL 可能是数字 0 或 void空指针会产生歧义传 NULL 易匹配 int 重载而非指针重载强转 voidNULL 还会报错。C11 新增 nullptr 关键字仅能转为各类指针无法转整数完美解决空指针类型混淆问题。感谢观看悠仁さん