【初阶与进阶C++详解】第一篇:C++入门知识必备

⭐️本篇博客我要给大家分享一下C++入门知识。希望对大家有所帮助。
⭐️ 博主码云gitee链接:码云主页

目录

前言

💎一、C++关键字

💎二、命名空间

        🏆1.命名空间定义

        🍍作用

         🍍介绍::

       🍍1. 普通命名空间

        🍍2.命名空间的嵌套定义

        🍍3.同一个工程中可以有多个相同名称命名空间,编译器最后会合成到同一个命名空间中去

        🏆2.命名空间的使用

💎三、C++输入和输出

💎四、缺省函数

        🏆1.缺省参数概念

        🏆2.缺省参数分类 

💎五、函数重载

        🏆1.函数重载概念和介绍

         🏆2.为什么C语言不支持函数重载,C++支持函数重载,C++是如何支持函数重载

        🏆extern"C" 

💎六、引用

        🏆1.引用的概念和特性

        🏆2.常引用 

                🍍做参数

               🍍做返回值 

                🍍两者比较 

                🍍引用和指针的区别 

💎七、内联函数

        🏆1.概念

        🏆2.特性 

💎八、auto关键字

        🏆1.介绍

        🏆2.使用方法 

        🏆3.不能使用场景

        🏆 typeid

💎九、基于范围的for循环

💎十、指针空值--nullptr

💎总结


前言


💎一、C++关键字

🧡C++又新增了31个关键字,一共63个关键字

image-20211009155405225

💎二、命名空间

🧡在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的,一个命名空间就相当于定义了一个新的作用域(隔离作用),命名空间中的所有内容都局限于命名空间中,可以定义变量,定义函数。

        🏆1.命名空间定义

🧡定义命名空间,需要使用到namespace关键字,namespace定义的是一个域,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员,成员还是全局变量,命名空间不影响声明周期,全局变量也会分配空间,命名空间只能放在全局,命名空间不会改变变量生命周期

        🍍作用

🧡解决C语言命名冲突,下面就是,输出scanf时候,会优先到局部变量去寻找,不回去头文件<stdio.h>中寻找,前面定义scanf不会报错,但后面使用的时候就会报错

int scanf =10;
int strlen = 20;

scanf ("%d", &scanf);
printf("%d\n", scanf);
printf("%d\n", strlen);

         🍍介绍::

🧡:: 域作用限定符号,指定访问域

定义一个域

namespace Penguins_not_bark{
    int scanf = 10;
}

使用:

int main (){
    printf("%d",Penguins_not_bark::scanf);
}

🧡优先使用bit这一个域中的参数,并且不会与stdio.头文件中的函数发生冲突,如果只有::说明前面是全局域

       🍍1. 普通命名空间

namespace Penguins_not_bark
{
	int a = 10;
	int b = 20;

	int Add(int x, int y)
	{
		return x + y;
	}
}

        🍍2.命名空间的嵌套定义

namespace Penguins_not_bark
{
	int a = 10;
	int b = 20;
    namespace Penguins
 {
	 int x = 10;
	 int y = 20;

	 int Add(int x, int y)
	 {
	 	return x + y;
	 }
 }
}

        🍍3.同一个工程中可以有多个相同名称命名空间,编译器最后会合成到同一个命名空间中去

namespace Penguins_not_bark
{
	int a = 10;
	int b = 20;

	int Add(int x, int y)
	{
		return x + y;
	}
}

namespace Penguins_not_bark
{
	int x = 10;
	int y = 20;
}

        🏆2.命名空间的使用

        1.指定命名空间,加命名空间名称及作用域限定符,每个地方都要指定命名空间   

int main()
{
	std::cout<<"hello!"<<std::endl;
    //这里我们可以理解为作用域限定符"::"的使用,让我们在lin这个命名空间中找到了a这个变量
	return 0;
}

        2.使用using namespace 命名空间名称,相当于库里面东西都到全局域里面了,但是如果我们库里面的东西和全局域冲突的话就没办法解决了

using namespace std;//关键字using的使用将命名空间展开到全局

int main()
{
	cout<<"hello!"<<endl;
	return 0;
}

        3.对库里面的东西部分展开,引入使用using将命名空间中成员引入,这样使用变量的时候不需要加上命名空间了

using namespace std::cout;
using namespace std::endl;
int main()
{
	cout<<"hello!"<<endl;
	return 0;
}

💎三、C++输入和输出

🧡使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含< iostream >头文件以及std标准命名空间

🧡使用C++输入输出更方便,不需增加数据格式控制,自动识别类型

🧡cout和cin是函数重载和运算符重载

🧡>> 流提取运算符    << 流插入运算符

🧡<cstring>有命名空间 , <string.h>没有命名空间

💎四、缺省函数

        🏆1.缺省参数概念

🧡缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参

🧡缺省参数在调用的时候更加灵活

void StackInit (struct Stack* ps,int InitCapacity = 4){
    ps->a = (int*) malloc(sizeof(int)* InitCapacity) ;
    ps->size = 0;
    ps->capacity = InitCapacity;
}

int main(){
    struct Stack stl;
    //假设我知道栈里面至少要存100个数据StackInit(&st1,100);
    struct Stack st2;
    //假设我知道栈里面最多要存10个数据StackInit(&st2,10);
    struct Stack st3;
    //假设我丕知旗x果炽服众i以StackInit(&st2);
    return 0;
}

🧡半缺省参数必须从右往左依次来给出,不能间隔着给,因为传参是从左往右
🧡缺省参数不能在函数声明和定义中同时出现,所以声明的时候缺省参数,定义的时候不可以

//a.h
void TestFunc(int a = 10);
// a.c
void TestFunc(int a = 20)
{}
void TestFunc(int a = 0)
{
    cout<<a<<endl;
}
int main()
{
    TestFunc(); // 没有传参时,使用参数的默认值
    TestFunc(10); // 传参时,使用指定的实参
}

        🏆2.缺省参数分类 

🧡全缺省,全部参数都有默认值

void TestFunc(int a = 10, int b = 20, int c = 30)
{
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
}

🧡半缺省,缺省部分参数 ,但是缺省的参数必须从右往左,并且是连续的,半缺省传值必须至少传一个

void TestFunc(int a, int b = 10, int c = 20)
{
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
}

💎五、函数重载

        🏆1.函数重载概念和介绍

🧡C语言不可以定义相同的名字的函数,C++可以定义相同名字的函数,但是要求参数类型不同,或者参数个数不同,或者参数顺序(不同类型的形参)不同,和返回值没有关系

 🧡虽然都是调用Add但是,会分别调用对应的类型

int Add(int left, int right){
    return left+right;
}
double Add(double left, double right)
{
    return left+right;
}
long Add(long left, long right)
{
    return left+right;
}

int main()
{
    Add(10, 20);
    Add(10.0, 20.0);
    Add(10L, 20L);
    return 0;
}

         🏆2.为什么C语言不支持函数重载,C++支持函数重载,C++是如何支持函数重载

编译连接的过程:
f.h f.cpp main. cpp
🧡1、预处理--头文件展开+宏替换+去掉注释+条件编译

        f.i main.i
🧡2、编译--检查语法,生成汇编代码

        f.s main.s
🧡3、汇编―--把汇编代码转成二进制机器码

        f.o  main.o
🧡4、链接--链接到一起生成可执行程序

        a.out

 🧡编译后链接前,a.out的目标文件中没有Add的函数地址,因为Add是在头文件中声明的,而声明是没有创建函数栈帧,所以声明是没有地址的但是编译器还是让程序过了

call(?)

之后符号表汇总后再将这些call后面地址填好,在链接阶段完成

#include <iostream>
using namespace std;

int add(int a, int b);
double add(double a, double b);

🧡之后链接的时候将上述文件链接到一起,同时到其他文件中取找到Add函数的地址,同时每一个目标文件都会生成一个符号表其中f.o文件的符号表中有Add函数的地址,找到函数地址的时候将函数地址填入之前编译部分跳过的部分(call),如果没有找到就会报链接错误

🧡C++为了区分第二个相同的函数名,会用函数名修饰规则支持函数重载,那么第一个函数会变成_Z3addii(地址),第二个函数会变成_Z3adddd(地址),两个函数地址不一样。函数修饰【_Z+函数长度+函数名+类型首字母】,int* 的话,就转化为Pi

🧡但是C语言的函数地址是直接拿函数名作为函数,编译阶段就会报错,没有前缀后缀 ,没有函数名修饰规则

🧡C++函数名修饰规则会把参数首字母带入,所以参数不同函数名就不同

🧡不同编译器下的修饰规则是不一样的

        🏆extern"C" 

🧡有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。可以直接加在函数声明的前面,也可以括起来多个函数声明。

extern "C" int Add(int left, int right);
int main()
{
    Add(1,2);
    return 0;
}

🧡但是这个函数不能重载

🧡C++和C可以互相调用,但是java不行

//如果c++调用C那么此时所有的exextern "C"替换为EXTERN_c
#ifdef __cplusplus
    #define EXTERN_c extern "C"
//如果C调用C那么此时所有的EXTERN_C替换为什么都没有,不影响
#else
    #define  EXTERN_C
#endif

EXTERN_C void add(int a, int b);

简化法

#ifdef __cplusplus
extern "C"
    {
#endif
    int add(int a, int b);
#ifdef __cplusplus
    }
#endif

但此时不支持函数重载

💎六、引用

        🏆1.引用的概念和特性

🧡引用不是新定义一个变量,而是给已存在变量取了一个别名,它和它引用的变量共用同一块内存空间引用类型必须和引用实体是同种类型

🧡引用在定义时必须初始化
🧡一个变量可以有多个引用
🧡引用一旦引用一个实体,再不能引用其他实体

int a = 10;
int& b = a;

int e = 20;
b = e;

上面b是a的引用,b = e(就是赋值),因为b和a地址一样,所以b和a的值都会变成20,但是地址还是原来的样子。

类型& 引用变量名(对象名) = 引用实体;

void TestRef()
{
    int a = 10;
    int& ra = a;//<====定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}

        🏆2.常引用 

void TestConstRef()
{
const int a = 10;
//int& ra = a; // a为常量,加了const不能修改,那自己和别名都不可以修改,此行为属于权限放大
//要变成cosnt int& ra = a;

int b = 10;
int& rb = b;
const int& crb = b;//此行为可以使用,由可以改变变成不可以改变,属于权限缩小

int c = 10;
double b = 1.1;
b = c;//隐式类型转换,中间会产生临时变量(存放的是浮点数的整数部分)

const int& b = 10;
double d = 12.34;
//int& rd = d; // 权限放大,是可读可写的
const int& rd = d;//中间产生临时变量,rd为临时变量的·别名,临时变量具有常性,不能改变,所以加const(权限没有放大,权限只是只读)就不会报错了
}

                🍍做参数

用传引用比传值要快的很多,引用和传址速度差不多,但是引用比传址更好理解,减少拷贝提高效率,输出型参数(将参数返回)。

void Swap(int& left, int& right)
{
    int temp = left;
    left = right;
    right = temp;
}

               🍍做返回值 

 🧡传值返回,ret引用的不是C,是一个临时变量(返回值类型就是临时变量类型,函数结束,函数就销毁了,所以就拷贝给临时变量,临时变量暂时存在寄存器),临时变量具有常性(常性不能修改,不加const就是权限放大),所以要加const,同时函数返回的是C的别名

int Add(int a,int b){
    int c = a + b;
    return c;
}
int main(){
    const int& ret = Add(1,2) ;//不加const就错了
    return 0;
}

🧡传引用返回,下面代码是错误的,函数返回的是临时变量,不能定义临时变量的别名,临时变量具有常性,要加上const才对

int A() {
	int n = 0;
	++n;
	return n;
}

int main ()
{

    int& ret = A(); //正确写法,const int& ret = A();           
	cout << ret << endl;
	return 0;
}

🧡改成下面只是不会报错,函数返回的是n的别名,ret就是n的别名,n和ret地址是一样的

🧡但是函数结束,函数销毁,此时打印ret就相当于再次访问被销毁的空间,打印的是随机值或者是1,取决于编译器(看数据有没有被覆盖)

int& A() {
	int n = 0;
	++n;
	return n;
}

int main ()
{

    int& ret = A();            
	cout << ret << endl;
    cout << ret << endl;
    cout << ret << endl;
	return 0;
}
//输出: 1 随机值 随机值

🧡 传引用返回正确的使用方法

int& A() {
	static int n = 0;
	++n;
	return n;
}

int main ()
{

    int& ret = A();            
	cout << ret << endl;
	return 0;
}

🧡C是一个局部变量,出作用域就销毁了,第一次调用,ret指向了一个被销毁的空间,打印7是因为恰好结果和被销毁前使用了同一内存,第二次调用,打印内容可能两次打印之间被改改变了(不安全)

int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);
    Add(3,4);
    cout << "Add(1, 2) is :"<< ret <<endl;
    cout << "Add(1, 2) is :"<< ret <<endl;
    return 0;
}
//输出:7 随机值

🧡下面的值是3,因为初始化只执行一次,ret依旧是C的别名,就算函数销毁了,C在静态区

int& Add(int a, int b)
{
    static int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);
    Add(3,4);
    cout << "Add(1, 2) is :"<< ret <<endl;
    return 0;
}

 🧡传值返回是返回拷贝,传引用返回返回的是别名(临时变量),如果是以下代码,是引用,返回别名,存放到ret里面,所以输出的ret就是3,但仍然是错误,因为返回的C是一个局部变量,出作用域后销毁了

int& Add(int a, int b)
{
    int c = a + b;
    return c;
}

int main()
{
    int ret = Add(1, 2);
    Add(3, 4);
    cout << "Add(1, 2) is :"<< ret <<endl;
    cout << "Add(1, 2) is :"<< ret <<endl;//输出3 3 
    return 0;
}

 🧡如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统里,则必须使用传值返回。

🧡引用返回使用,当出了函数作用域,n还在就可以减少拷贝,此时使用引用返回

int& AD(){
    static int n = 0;
    ++n;
    return n;
}

int main ()
{
    int& ret = AD();
}

总之,当变量出了作用域还在的话,就可以用引用返回。

                🍍两者比较 

🧡传值返回会产生拷贝,传引用传参和传引用作返回值不会拷贝,直接返回变量的别名,避免深拷贝,可以提高效率

                🍍引用和指针的区别 

int main(){
    int a = 10;

    //在语法上,这里给a这块空间取了一个别名,没有新开空间
    int& ra = a;
    ra = 20;

    //在语法上,这里定义个pa指针变量,开了4个字节,存储a的地址
    int* pa = &a;
    *pa = 20;
    return 0;
}

🧡引用和指针的不同点:

        1.从语法上来说,引用定义一个变量的别名,指针存储一个变量的地址

        2.引用在定义时必须初始化,指针没有要求,int& ra;(×) int* p;(√)

        3.引用在初始化时引用一个实体后,就不能在引用其他实体,而指针可以在任何事之后指向任何一个同类型的实体

        4.没有NULL引用,但有NULL指针

        5.在sizeof中含义不同,引用结果为引用类型大小,但指针始终是地址空间所占字节个数(有占4个字节和8个字节),从语法角度:引用没有开辟格外空间,指针开辟4或8个字节。底层角度实验方式都是一样的。

        6.引用自加及引用实体增加1,指针自加及指针向后便宜一个类型的大小

        7.有多级指针,没有多级引用

        8.访问实体方式不同,指针需要显示解引用,引用编译器自己处理

        9.引用比指针使用更加安全

int* p = NULL;
int*& rp = p;

 🧡rp类型是int*, 是p的引用

💎七、内联函数

        🏆1.概念

🧡C语言为了避免小函数建立栈帧,提供宏函数,宏函数在预处理阶段展开(但是也不一定,只是一种建议,需要看此函数是否构成内联函数)。

        优点:提高性能,增强代码复用性

        缺点:不支持调试,宏函数语法复杂,容易出错,没有类安全检查

🧡以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。

🧡release版本里面,没有call来开辟函数栈帧(优化)

🧡在debug版本,按照以下配置,也可以将debug消除call

inline int Add(int left,int right){
    return left + right;
}
int main(){
    int ret = 0;
    ret = Add(1,2);
    return 0;
}

🧡假设上面的函数有100条指令(一条汇编代码对应一条指令),调用上面的函数10次,函数栈帧总共会有110条指令(函数内有100条指令,十次调用用了10次call),inline调用总共就是1000条指令(每次调用都要展开)

🧡指令变多意味,编译出来可执行程序变大,内存占用越多

        🏆2.特性 

🧡结论:平调用小函数建议定义成inline 

        1.内联是空间换时间的做法,省去函数调用的开销,所以代码很长或者有循环和递归的函数不适合使用内联函数

        2.内联函数只是一个建议,不是百分百执行,具体根据函数大小,如果函数太大或者有递归,编译器优化时会忽略内联

        3.inline不建议声明和定义分离,分离会导致链接错误,因为inline被展开了,就没有函数地址了,链接就会找不到,内联函数声明不能放在头文件,要放在源文件

        4.内联函数在不同源文件实现和调用会导致函数链接错误,符号表找不到地址

//下面是错误的代码
// F.h
#include <iostream>

using namespace std;
inline void f(int i);

// F.cpp
#include "F.h"
void f(int i)
{
    cout << i << endl;
}

// main.cpp
#include "F.h"
int main()
{
    f(10);
    return 0;
}

🧡一个在头文件用inline,一个在主函数不用inline,会导致链接错误。

🧡解决办法,内联函数声明和定义在同一个文件下,之后在其他文件直接调用就可以了

🧡如果在一个文件下内联函数声明并定义了,但是又在另外一个文件声明了,会报错,因为会优先展开声明,但是展开的时候,符号表没有内联函数的地址,链接的时候会报错

 🧡C++替换宏的方法:

        1.函数定义用内联函数

        2.常量定义用const

💎八、auto关键字

        🏆1.介绍

🧡auto(自动)修饰的变量,是具有自动存储器的局部变量,用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&,auto看的是“ = ”之后变量的类型。

int main()
{
    int a = 10;
    auto b = a;//类型声明成auto,可根据a的类型自动推导b
}

 🧡当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量

void TestAuto()
{
    auto a = 1, b = 2;
    auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

        🏆2.使用方法 

🧡与指针结合使用

int main()
{
    int x = 10;
    auto a = &x;//int*
    auto* b = &x;//int*
    auto& c = x;//int
}

        🏆3.不能使用场景

🧡auto不能作为函数的参数,也不能作为返回值,必须要有值赋值给他,要初始化

// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}

 🧡auto不能直接用来声明数组,编译器需要根据数组的类型去开辟数组的空间,而使用auto去声明数组,编译器无法推导,就不能去用auto去声明。

void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};
}

        🏆 typeid

打印变量类型 

int b = 10;
cout << typeid(b).name() << endl;

🧡打印出来的是b的类型,是 int ,typeid返回的是一个字符串

💎九、基于范围的for循环

🧡for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

🧡依次取array中的数据,赋值给e,所以e只是拷贝,所以要写成auto& 将e变成array的别名

🧡范围for的array必须是数组的地址,下面就不可以了,因为范围不确定

void TestFor(int array[])
{
    for(auto& e : array)
    cout<< e <<endl;
}

void TestFor()
{
    int array[] = { 1, 2, 3, 4, 5 };
    for(auto& e : array)   //auto&e是引用array数组中的元素,效果是将元素乘2,直接改变原来数组
        e *= 2;
    for(auto e : array)    //自动遍历依次取出array中的元素赋值给e,直到结束,不会印象原来的数组
        cout << e << " ";
    return 0;
}

🧡注意:可以用continue来结束本次循环,也可以用break来跳出整个循环

 🧡条件:

        1.for循环迭代的范围必须是确定的,对于数组而言,就是数组中第一个元素和最后一个元素的范围
        2.迭代的对象要实现++和--的操作

💎十、指针空值--nullptr

🧡C++中最好nullptr,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同,在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的,定义为

#define NULL ((void *)0)


🧡NULL,宏定义为0,NULL被替换为0,所以NULL和0一样的,所以后时候在使用时,就默认八NULL当作数字0,如果要使用作为指针的话,必须对其进行强转(void *)0

#define NULL 0

💎总结

🧡断断续续的看了一个星期左右才搞懂了这些知识,知识很多很杂,不仅现在学了,以后还要再次体会。

本资源是压缩包形式的, 里面包含 本书,里面是pdf格式的, 带书签目录,本书是完整版的。 资源都是我自己用过的,不骗大家。 本书作者: 肖俊宇 吴为胜; 出版社: 电子工业出版社 内容简介: 《由浅入深学C++:基础、进阶与必做300题(含DVD光盘1张)》是C++语言入门教程,较为系统地介绍了C++语言的基础内容。本书共分为3篇22章,详细介绍了C++语言的基础知识、面向对象、标准模块、底层开发和综合案例。本书循序渐进地讲述了C++的基础知识C++程序的组成及其开发过程、C++程序中的数据、表达式和语句、控制程序流程、数组与字符串、指针与引用、使用函数、函数模板、错误和异常处理、宏和预编译、面向对象的开发、封装、继承、多态、类模板、文件流、标准模板库STL和编程实践等内容。 《由浅入深学C++:基础、进阶与必做300题(含DVD光盘1张)》涉及面广,从基本知识到高级内容和核心概念,再到综合案例,几乎涉及C++开发的所有重要知识。本书适合所有想全面学习C++开发技术的人员阅读,尤其适合没有编程基础的C++语言初学者作为入门教程,也可作为大、中院校师生和培训班的教材,对于C++语言开发爱好者,本书也有较大的参考价值。 章节目录: 第1篇 C++基础篇 第1章 C++概述 1 1.1 引言 1 1.1.1 C++的历史沿革 1 1.1.2 入门C++ 2 1.1.3 编程思想的转变 3 1.2 C++概述 4 1.2.1 C++的特征 5 1.2.2 C与C++的比较 5 1.2.3 C++的应用领域 6 1.3 C++源程序的组成 6 1.3.1 基本组成元素 7 1.3.2 标识符 8 1.3.3 保留字 8 1.3.4 符号 8 1.4 C++集成开发环境——DEV-C++ 9 1.4.1 选择C++编译器 9 1.4.2 安装DEV-C++ 10 1.4.3 DEV-C++ IDE简介 11 1.5 第一个C++程序——Hello World 11 1.5.1 创建源程序 11 1.5.2 编译运行 13 1.6 小结 14 1.7 习题 14 第2章 变量与数据类型 18 2.1 常量和变量 18 2.1.1 常量 18 2.1.2 变量 21 2.1.3 变量的定义及赋值 22 2.1.4 变量的应用示例 24 2.2 基本数据类型 25 2.2.1 基本数据类型概述 25 2.2.2 整型数据类型 26 2.2.3 浮点型数据类型 27 2.2.4 字符型数据类型 29 2.2.5 布尔型数据类型 30 2.3 变量的作用域 31 2.4 类型转换 32 2.4.1 隐式转换 32 2.4.2 显式转换 33 2.5 小结 34 2.6 习题 34 第3章 表达式与语句 39 3.1 运算符 39 3.1.1 运算符概述 39 3.1.2 算术运算符 40 3.1.3 自增和自减运算符 42 3.1.4 赋值运算符 43 3.1.5 关系运算符 44 3.1.6 逻辑运算符 45 3.1.7 条件运算符 46 3.1.8 逗号运算符 47 3.1.9 位运算符 48 3.1.10 sizeof运算符 49 3.2 运算符的优先级和结合性 50 3.3 表达式 51 3.4 语句 53 3.4.1 空格的作用 53 3.4.2 语句块 54 3.4.3 赋值语句 55 3.4.4 空语句 56 3.5 小结 57 3.6 习题 57 第4章 流程控制结构之顺序结构 63 4.1 程序流程图 63 4.2 表达式语句 64 4.3 格式化输入/输出 65 4.3.1 标准输入流cin 65 4.3.2 标准输出流cout 66 4.3.3 输出流cerr和clog 68 4.4 格式控制函数 69 4.5 格式控制符 71 4.5.1 控制不同进制的输出 72 4.5.2 控制输出宽度 72 4.5.3 控制输出精度 73 4.6 顺序结构综合应用 74 4.7 小结 75 4.8 习题 75
6、 函数模板和类模板 3 6.1函数模板 4 6.1.1为什么要有函数模板 4 6.1.2函数模板语法 5 6.1.3函数模板和模板函数 6 6.1.4函数模板做函数参数 6 6.1.5函数模板遇上函数重载 8 6.1.6 C++编译器模板机制剖析 10 6.2类模板 18 6.2.1为什么需要类模板 18 6.2.2单个类模板语法 18 6.2.3继承中的类模板语法 20 6.2.4类模板语法知识体系梳理 21 6.2.5类模板中的static关键字 23 6.3类模板在项目开发中的应用 25 6.4作业 29 7、C++的类型转换 29 7.1 类型转换名称和语法 29 7.2 类型转换一般性介绍 29 7.3 典型案例 30 7.3.1 static_cast用法和reinterpret_cast用法 30 7.3.2 dynamic_cast用法和reinterpret_cast用法 31 7.3.3 const_cast用法 33 7.4 总结 33 8、异常处理机制专题 33 8.1 异常处理的基本思想 34 8.1.1传统错误处理机制 34 8.1.2异常处理的基本思想 34 8.2 C++异常处理的实现 35 8.2.1异常基本语法 35 8.2.2栈解旋(unwinding) 39 8.2.3异常接口声明 40 8.2.4异常类型和异常变量的生命周期 40 8.2.5异常的层次结构(继承在异常中的应用) 46 8.3标准程序库异常 47 8.4训练强化 51 9 C++输入和输出流 51 9.1 I/O流的概念和流类库的结构 51 9.2标准I/O流 53 9.2.1标准输入流 55 9.2.2标准输出流 59 9.3文件I/O 66 9.3.1文件流类和文件流对象 66 9.3.2C++文件的打开与关闭 67 9.3.3C++对ASCII文件的读写操作 69 9.3.4 C++对二进制文件的读写操作 74 9.4作业练习 75 10、STL实用技术专题 79 10.1 STL(标准模板库)理论基础 79 10.1.1基本概念 79 10.1.2容器 80 10.1.3迭代器 82 10.1.4算法 82 10.1.5C++标准库 82 10.1.6模板简要回顾 85 10.2容器 86 10.2.1 STL的string 86 10.2.2Vector容器 90 10.2.3Deque容器 96 10.2.4stack容器 101 10.2.5Queue容器 103 10.2.6List容器 105 10.2.7优先级队列priority_queue 110 10.2.8Set和multiset容器 111 10.2.9Map和multimap容器 118 10.2.10容器共性机制研究 123 10.2.11其他 124 10.3算法 125 10.3.1算法基础 125 10.3.2STL算法中函数对象和谓词 138 10.3.3常用的遍历算法 148 10.3.4常用的查找算法 152 10.3.5常用的排序算法 154 10.3.6常用的拷贝和替换算法 156 10.3.7常用的算术和生成算法 157 10.3.8常用的集合算法 158 10.4 STL综合案例 159 10.4.1案例学校演讲比赛 159 10.4.2案例:足球比赛 161
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

penguin_bark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值