news 2026/4/15 4:47:08

C++入门基础知识

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++入门基础知识

C++关键字(C++98)

C++总计63个关键字,C语言32个关键字,用到了再详细学习。

命名空间

为什么要引入命名空间?用来解决名字冲突,使得代码模块化、可读性更高

什么是命名空间?

命名空间就是给代码加的「专属文件夹」,用来避免名字冲突,同时区分不同模块 / 库的代码,是 C++ 组织代码的核心机制。

命名空间的作用是什么?

解决名字冲突,代码模块化、可读性更高;

命名空间的定义?

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

// bit是命名空间的名字,一般开发中是用项目名字做命名空间名。namespace bit{// 命名空间中可以定义变量/函数/类型intrand=10;intAdd(intleft,intright){returnleft+right;}structNode{structNode*next;intval;};}//2. 命名空间可以嵌套//test.cppnamespaceN1{inta;intb;intAdd(intleft,intright){returnleft+right;}namespaceN2{intc;intd;intSub(intleft,intright){returnleft-right;}}}//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。// ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个// test.hnamespaceN1{intMul(intleft,intright){returnleft*right;}}注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中

命名空间怎么使用?

核心符号::: 是作用域解析符,用来指定命名空间成员;

三种使用方法:1.直接使用::号,如:命名空间名::变量名(在命名空间中存在的)2.在使用前使用:using 命名空间名::变量名,将变量解析出来就可以直接使用了3.将命名空间中的内容全部解析:using namespace 命名空间名;

注意:大型项目不要直接用 using namespace,避免冲突;优先用 命名空间::解析空间中的成员

#include<iostream>using namespace std;//c++库中所以东西都是放在std命名空间中的intmain(){cout<<" hello world "<<endl;return0;}法二: #include<iostream>//using namespace std;//c++库中所以东西都是放在std命名空间中的intmain(){std::cout<<" hello world "<<std::endl;return0;}//<<是流插入运算符,>>是流提取运算符

缺省参数

什么是缺省参数?

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

参则采用该形参的缺省值,否则使用指定的实参。所以简称备胎参数。如下图运行结果:

缺省参数的分类?

全缺省参数:

注意:传参调用时必须从左往右依次传参调用,如下图中的操作会报错。

半缺省参数:

注意:缺省参数必须从左往右依次连续缺省,否则会报如下错误。

函数重载

什么是函数重载?

函数重载是在同一作用域中声明几个功能类似的同名函数,且函数参数不同,其中参数不同又包含:参数的类型不同,参数个数不同和参数类型的顺序不同【如void Func1(int i, char ch); 和void Func(char ch, int i ); 构成函数重载】。对有没有返回值没有影响,所以只有返回值不同时,不能构成函数重载。

c++是如何支持函数重载的?为什么c语言不支持函数重载?

C++ 支持函数重载而 C 语言不支持,核心原因在于编译链接阶段的符号处理机制存在本质区别:

程序从源码到可执行文件需要经过4个阶段:list.h list.c test.c

预处理
生成:list.i test.i
头文件的展开/宏替换/条件编译/去掉注释
编译
生成:list.s test.s
检查语法,生成汇编代码
汇编
生成:list.o test.o
汇编代码转成二进制的机器码
链接将两个目标文件链接到一起

编译时,C 编译器在符号表生成的函数名就是原来的函数名,同一函数链接时会发生冲突。所以c语言中无法支持重载.

为支持重载,C++ 编译器在编译时执行函数名修饰规则:将函数名、参数类型、个数、顺序等信息编码为唯一的内部符号名。如 Linux g++ 下,void add(int)会被修饰为_Z3addi,void add(double)会被修饰为_Z3addd,修饰后的符号名完全不同,链接器可精准区分。【同时:不同编译器规则不同:Linux g++ 采用_Z+函数长度+函数名+类型首字母】

引用

什么是引用?

引用是给已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

引用的定义

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

inta=1;int&ra=a;//ra是a的引用,引用就是给已经存在的变量取一个别名,此时a再取一个名称raint&b=a;int&c=b;

注意:引用类型必须和引用实体是同种类型

引用特性

1. 引用在定义时必须初始化

2. 一个变量可以有多个引用

3. 引用一旦引用一个实体,再不能引用其他实体,如果引用了,其地址不变,若引用的变量有数值,其原来的值会发生改变。

地址变量,值变为了2。

常引用

一:constinta=10;//int& ra = a; // 该语句编译时会出错,a为常量,就是说a是只读的;b的类型是int,是可读可写的,所以不行。constint&ra=a;// int& b = 10; // 该语句编译时会出错,b为常量constint&b=10;二:intc=1;int&d=c;constint&e=c;//ok的,c是可读可写的,e只可读总结:引用取别名时,变量访问的权限可以缩小,不能放大//指针:constint*cp1=&a;//int* p1 = cp1;//不能,属于权限的放大int*p2=&c;constint*cp2=p2;//可以,属于权限的缩小三:inti=1;doubledi=i;//隐式类型转换//double& ri = i;//不可行//floatt& rf =i;//不可行,但是加const就可以,如下图

注意:在变量之间,没有权限缩小和放大的关系,只有引用和指针才有。在实际静态/动态库中只会提供少量函数给程序用,这些函数+extern “C”,但其实一般提供tcmalloc和tcfree给外面用

引用有哪些使用场景呢?

1.做参数

作用:做输出型参数;提高运行效率

voidSwap_c(int*p1,int*p2){inttmp=*p1;*p1=*p2;*p2=tmp;}//c++中使用引用做参数voidSwap_cpp(int&r1,int&r2){//r1对应a的别名,r2对应b的别名inttmp=r1;r1=r2;r2=tmp;}intmain(){inta=1,b=2;Swap_c(&a,&b);Swap_cpp(a,b);return0;}
2.做返回值

作用:少创建一个临时对象,提高程序效率

//传值返回:把函数里的变量拷贝一份给调用者,这份拷贝就是临时变量,用完就销毁。intCount1(){staticintn=0;n++;returnn;//会产生一个临时变量,具有常性,会多产生空间}//传引用返回:把变量n的别名给调用者,不用拷贝,没有临时变量,不会产生空间int&Count2(){staticintn=0;n++;returnn;//直接返回n}intmain(){//int& r1 = Count1();//编译不通过constint&r1=Count1();int&r2=Count2();return0;}

没有static时

int&Add(inta,intb){intc=a+b;returnc;}intmain(){constint&ret=Add(1,2);Add(3,4);cout<<"Add(1, 2) = "<<ret<<endl;return0;}//结果如下:运行结果有误原因是:c是一个局部变量,出了Add函数,c就不在栈帧里了,解决办法就是在c前加static修饰

解决问题之后:

static修饰的变量在函数调用时值执行一次,所以运行结果为3不变。

总结:一个函数要使用引用返回时,返回变量出了函数的作用域还存在,就可以使用引用返回,否则,不可以使用。

内联函数

为什么引入内联函数?

当我们频繁调用一个函数时,需要创建栈帧,是有消耗的,因此,为解决这个问题:1,c语言中使用宏函数,但是其可读性比较差,2,c++使用内联函数,编译时C++编译器会在调用内联函数的地方展开,目的是以空间换时间,但是函数没有地址。

什么是内联函数?

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调

用建立栈帧的开销,提升程序运行的效率。

//内联函数inlinevoidSwap(int&x1,int&x2){inttmp=x1;x1=x2;x2=tmp;}intmain(){inta=1,b=2;Swap(a,b);return0;}

如下图:在反汇编中,已经在调用函数的地方将函数展开

使用内联函数不展开情况:
//内联函数inlinevoidSwap(int&x1,int&x2){inttmp=x1;x1=x2;x2=tmp;//当内联函数中代码较多时,就不展开了tmp=x1;x1=x2;x2=tmp;tmp=x1;x1=x2;x2=tmp;tmp=x1;x1=x2;x2=tmp;tmp=x1;x1=x2;x2=tmp;tmp=x1;x1=x2;x2=tmp;}intmain(){inta=1,b=2;Swap(a,b);return0;}

总结:一般内联适用于小函数,其次递归或者比较长的都不适合内联

内联函数的特性:

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会

用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运

行效率。

  1. 一般内联适用于小函数,其次递归或者比较长的都不适合内联

  2. inline不能声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

auto关键字(C++11)

auto的作用:推导出变量的数据类型,由编译器在编译时期推导而得。

注意:使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。

注意:

1.用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&。

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

3.auto不能做参数,数组也不能用auto

范围for(c++11)

特点:写起来比较简洁

使用案例:

//范围forintmain(){intarr[]={1,1,1,1,1,1};//要求将数据中的每一个值乘2,再打印一遍//c++11for(auto e:arr){//第二空只能是数组名,不能是数组指针e*=2;//并不改变数组中的值}for(auto e:arr){cout<<e<<" ";}cout<<endl;//改变数组中的值,使用引用for(auto&e:arr){e*=2;}for(auto e:arr){cout<<e<<" ";}cout<<endl;}

指针空值nullptr(C++11)

使用案例:

//指针空值nullptr(C++11)voidfun(intn){cout<<"整形"<<endl;}voidfun(int*p){cout<<"整形指针"<<endl;}intmain(){//cint*p1=NULL;//c++int*p2=nullptr;fun(0);fun(NULL);//预处理后fun(0)fun(nullptr);}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 4:42:26

Python 协程任务取消机制解析

Python 协程任务取消机制解析 在现代异步编程中&#xff0c;Python的协程&#xff08;Coroutine&#xff09;凭借其轻量级和高效率成为处理并发任务的重要工具。协程任务的取消机制却常被开发者忽视&#xff0c;导致资源泄露或程序逻辑异常。本文将从多个角度解析Python协程任…

作者头像 李华
网站建设 2026/4/15 4:38:33

A股站稳4000点:是反弹起点,还是牛市序幕?

今日A股在利空消息面下逆势反弹&#xff0c;成功站稳4000点整数关口&#xff0c;伴随成交量有效放大&#xff0c;呈现全线普涨态势。科技板块企稳、金融消费板块回升&#xff0c;作为市场风向标的腾讯控股早盘高开&#xff0c;港股午后也逐步企稳。这一系列信号背后&#xff0c…

作者头像 李华
网站建设 2026/4/15 4:36:12

配置 PyCharm(汉化版操作指南)

本文详细介绍了PyCharm汉化版配置Python 3.13.13环境的完整步骤。首先通过"文件→设置→Python解释器"路径进入配置界面&#xff0c;选择"添加本地解释器"并创建Virtualenv虚拟环境&#xff0c;指定Python3.13.13安装路径中的python.exe作为基础解释器。重…

作者头像 李华
网站建设 2026/4/15 4:35:13

mysql如何记录用户登录审计_配置插件追踪IP与时间

MySQL 8.0.19 启用 audit_log 插件需安装插件、配置 audit_logFORCE_PLUS_PERMANENT、audit_log_formatJSON、audit_log_policyLOGINS&#xff08;或 ALL&#xff09;&#xff0c;注意其不记录 Unix socket 登录&#xff0c;且密码错误等认证失败细节需结合错误日志分析。mysql…

作者头像 李华