当前位置: 首页 > news >正文

c++基础语法

文章目录

  • 前言
  • 命名空间
    • 命名空间的使用
  • 缺省参数
    • 缺省参数的使用
  • 函数重载
    • 函数重载的作用
    • 函数重载的使用
    • 函数重载原理
  • 引用
    • 引用的使用
    • 引用的使用场景
    • 引用和指针
  • extern C
  • inline
  • auto
  • 范围for
  • nullptr

前言

大家好我是jiantaoyab,这篇文章给大家带来的是c语言没有的一些特性之一,是c++的基础语法,对后面的学习有帮助,后面我将逐步编写类和对象、STL容器等C++笔记,欢迎大家关注我!

命名空间

当程序达到一个规模后,会不可避免的使用到相同的函数名和标识符导致冲突,可以使用namespace封装到一个命名空间中,一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中

同一个工程中能存在相同的命名空间,相同名字的命名空间会合并到一起

作用域:变量的有效范围,从定义的起点开始,到定义变量之前最近的一对括号确定

命名空间的使用

//1.使用using使用命名空间成员之一
using jiantao::n;
//2.using namespace jiantao
//全部展开,失去封装的效果,不建议这样使用
namespace jiantao
{int n = 10;//可以嵌套使用namespace id{int b = 2;}
}int main()
{cout << n << endl; //using jiantao::n; 直接用cout << jiantao::n << endl; //一般的使用方法cout << jiantao::id::b << endl; return 0;
}

缺省参数

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

缺省参数的使用

注意点

  • 半缺省参数必须从右往左给,不能间隔给
  • 缺省参数不能在定义和声明中同时出现,建议在声明中写
  • 缺省值必须是全局变量或者是常量
void fun()
{cout << "fun()" << endl;
}//默认这里的参数会给值
void fun(int a ,int b=10,int c=20)
{cout << a << endl;cout << b << endl;cout << c << endl;}
int main()
{fun(1); fun(1,2);//传2的话b的值就是2
}

函数重载

函数重载是指在同一作用域内,声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,这组函数被称为重载函数

函数重载的作用

重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处

函数重载的使用

int add(int a, int b)
{return a + b;
}
double add(double a, double b)
{return a + b;
}
int main()
{add(1, 2);add(1.1, 1.2); //2个add构成重载return 0;
}

函数重载原理

Linux下,我定义了2个函数名字相同的函数,在gcc编译的时候,报错

image-20240309141027391

什么原因?

回忆一下一个程序编译链接的过程,在汇编的时候,会生成.o文件,.o文件是没有函数的地址的(声明和定义分开写),那么在链接的时候,会根据函数的名字去找地址,而在c语言中,不存在函数名字的修饰,根据函数的名字去符号表中找,假设在符号表中有Add(0x33123)和Add(0x332323),这在符号表中都冲突了,人家链接也不知道链接哪个

image-20240309143324511

而在c++中,存在函数名修饰规则,不同平台下不一样,在linux下大概为作用域+返回类型+函数名+参数列表,就能找到的函数的地址能链接上了

image-20240309143924393

重载大概的流程图

image-20240309144941774

我的知识有限,大家可以看看这篇 c++函数重载 里面有更详细的介绍

引用

引用不是新定义一个变量,而是给已经存在的变量起了一个别名,引用的变量和原来的变量共用一块内存空间

引用的使用

1.引用的类型和引用的实体必须的同类型的int a=10; int &b=a;2.引用在定义的时候必须初始化int &c=10 //error 引用的必须是一个对象const int a=10; int &b=a;//error a为常量
3.一旦一个引用被初始化指向一个对象,它就不能变为另一个对象的引用但一个对象可以有多个引用int a = 0;int& b = a;int& b = c; //ERRORint& c = a; //RIGHT
4.引用权限只能缩小,不能放大int a=10;const int &b=a;//✔ 权限缩小const int d = 10;int & f = d; //ERROR,这是权限的放大
5 临时变量本来是右值,是常量不能修改的double b = 1.1;int& i = d; //ERROR,存在类型转换,类型转换有临时变量const int& i2 = d //可以 

引用的使用场景

1.引用做参数 :提高效率,形参的改变能影响实参
int swap(int &x,int &y)
{}
使用引用传参,如果不改变参数的值,建议使用const引用2.引用做返回值:提高效率,修改返回变量(临时变量本来是右值,是常量不能修改的)
int& Add(int a,int b)
{int c=a+b; return c;
}
int main()
{int ret=Add(1,2);cout<<ret<<endl;
}

引用做返回值有一个重要的点,引用的这个返回对象在这个函数栈帧销毁的时候,还存在着才能使用引用返回。

int& Sub(int x, int y)
{int ret = x - y;return ret;
}int& f()
{int *p=(int *)malloc(4);return *p;//是可以的,p指向的空间还在return p;//error 指针p已经给销毁
}
int main()
{int& a = Sub(2, 1);
}  

image-20240309153633784

虽然编译通过了,但是上面的代码会存在非法访问的问题,Sub的返回值原来是临时变量,这里用了引用返回,那相当于int & ret = tmp,在调用完Sub后会回去访问ret的空间,假如Sub栈帧给销毁了,a所取到的值就是随机值,这里我们并没有马上使用这块空间才没报错。

image-20240309161456127

引用和指针

  • 引用在定义的时候必须初始化,指针不初始化也不报错
  • 引用一个对象之后就不能再引用别人对象,指针可以随意更改对象
  • 引用的大小是引用实体的大小,指针的大小是固定是4/8个字节
  • 引用不会开辟空间不占用内存
  • 引用加1是引用的实体加1,指针加1是向后偏移一个类型的大小

通过下面的汇编代码看出,引用和指针在使用的汇编指令是一样的

image-20240309164516106

extern C

大家有没有想过,如果我用c++写的程序,想去调用别人c写的库怎么去调用呢?

一会再回答这个问题,我们先来看看extern的用法。

extern是C语言中的一个关键字,一般用在变量名前或函数名前,作用是用来说明此变量/函数是在别处定义的,要在此处引用,在遇到此变量或函数的时候在其他文件中寻找其定义

extern int a;//声明变量a是在别的文件定义的,只是声明,没有分配内存
举个例子:   
比如我在test.cpp中 extern int num; extren void Print();
然后在fun.cpp 中  
int num = 1; //这里是定义变量  
void Print(){printf("Print()");} //这里是定义函数
这样子就能在test.cpp中使用这个num变量了 和 Print 这个函数了

想要在C++中调用c语言写的库,在vs2013下,需要执行下面操作

  1. 调试->属性->链接器 常规 ->附加库目录把库加上(Debug)

  2. 调试->属性->链接器 输入-> 附加依赖项 手动加入库的名字 xxx.lib

extern "C"
{//把头文件所在的目录包含#include "../../DS/DS/Stack.h" 
}

告诉C++编译器,extern “C”{}里面的函数是C编译器编译的,链接的时候用C的函数名规则去找,就可以链接上, 定义为extern的变量也会在外面去找

在C中调用c++写的库,要在cpp库中修改

//如果有__cplusplus 这个宏就用 extern "C" 替换 EXTRERN_C
#ifdef __cplusplus
#define EXTRERN_C extern "C" // C++静态库extern "C"告诉编译器以下函数按C的函数名修饰规则去处理
#else
#define EXTRERN_C  //这里走的是else 就是EXTRERN_C 什么都没有
#endifEXTRERN_C void StackInit(ST* ps); //运行后相当于 void StackInit(ST* ps)
EXTRERN_C void StackDestroy(ST* ps);
EXTRERN_C void StackPush(ST* ps, STDataType x);
EXTRERN_C void StackPop(ST* ps);
EXTRERN_C STDataType StackTop(ST* ps);
EXTRERN_C int StackSize(ST* ps);
EXTRERN_C bool StackEmpty(ST* ps);

inline

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销(使用内联函数在.o文件符号表不会生成函数的地址),内联函数提升程序运行的效率。

一般调用函数在汇编语言中是用call来调用的

image-20240312203723202

当把Add函数设置成内联函数后,再看看汇编,想要显示出效果需要在vs2013Debug下设置

image-20240312203904395

image-20240312204121429

image-20240312204047665

可以看到直接以函数的本体代替就像宏一样,但是会增加目标码的大小,会导致额外的换页行为,降低指令高速缓存装置的击中率。还有要注意的是inline只是对编译器的一个申请,不一定会采用

还有inline不建议声明的定义分离,分离会导致链接错误在小型、频繁调用的函数上,可以使用inline

小练习

A.使用inline关键字的函数会被编译器在调用处展开
B.头文件中可以包含inline函数的声明
C.可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数

A.不一定,因为inline只是一种建议,需要看此函数是否能够成为内联函数

B. inline函数不支持声明和定义分离开,因为编译器一旦将一个函数作为内联函数处理,就会在调用位置展开,即该函数是没有地址的,也不能在其他源文件中调用,故一般都是直接在源文件中定义内联函数的

C.inline函数会在调用的地方展开,所以符号表中不会有inline函数的符号名,不存在链接冲突。

auto

自动推导类型:类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型 ,auto会忽略顶层的const,而底层const被保留(顶层const是指针本身是个 常量,底层const是指针指向的对象是一个常量)

int main()
{const int a = 10;auto b = a; // int cout << typeid(b).name() << endl;//不管原来对象是不是const 要想成为const的auto 要在 auto前加上const //例如 const auto b =a; 这样定义出来的b就是带const属性的int x = 1;auto a = x; //intauto&b = x; //int&auto*c = &x;//int *return 0;
}

auto不能使用的场景

1.不能作为函数的参数
void Add(auto a) //error 编译器无法对a的实际类型进行推导
auto b //error
2.不能用来声明数组
auto arr[]={1,2,3}; //error    

范围for

int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7 };//范围for这个地方必须是数组名for (auto e: arr) //一个一个取arr的值放到e中{cout <<" "<< e; }cout << endl;//每个值加1for (auto&e : arr){e++;}cout << endl;for (auto e : arr){cout << " " << e;}cout << endl;}void printf_(int arr[]) for(auto e:arr)//error 数组传参的时候会退化为指针,不再是数组名字{cout<<e<<endl;}
}

nullptr

c++中用nullptr中比null好

void f(int)
{cout << "f(int)" << endl;
}
void f(int *)
{cout << "f(int *)" << endl;
}
int main()
{f(NULL);// NULL = 0 调用了f(int),本意是调用f(int*)f(nullptr);//调用f(int *)
}

相关文章:

c++基础语法

文章目录 前言命名空间命名空间的使用 缺省参数缺省参数的使用 函数重载函数重载的作用函数重载的使用函数重载原理 引用引用的使用引用的使用场景引用和指针 extern Cinlineauto范围fornullptr 前言 大家好我是jiantaoyab&#xff0c;这篇文章给大家带来的是c语言没有的一些特…...

【工作实践-07】uniapp关于单位rpx坑

问题&#xff1a;在浏览器页面退出登录按钮上“退出登录”字样消失&#xff0c;而在手机端页面正常;通过查看浏览器页面的HTML代码&#xff0c;发现有“退出登录”这几个字&#xff0c;只不过由于样式问题&#xff0c;这几个字被挤到看不见了。 样式代码中有一行为&#xff1a…...

服务层组件

目录 连接层(Connection Pool) SQL接口(SQL Interface) 查询缓存(Caches&Buffers) Management Services&Utilities 查询分析器(Parser) 优化器(Optimizer)...

【学习笔记】VMware vSphere 6.7虚拟化入门

VMware vSphere 6.7虚拟化入门课程介绍 课程内容 1、VMware vSphere 6.7虚拟化入门课程介绍 2、ESXi6.7控制台设置 3、使用vSpkere Host client管理虚拟机 4、VMware EsXi基础操作 5、VMware Esxi存储管理 6、管理ESXi主机网络与虚拟机网络 7、安装配置vCenter Server Applia…...

如何防范企业内部安全威胁?

1 用户行为分析&#xff08;UEBA&#xff09; 现代化的用户行为分析产品具有多种优势功能&#xff0c;使企业能够有效地检测内部威胁。用户行为分析软件通过收集和分析来自各种来源的数据来分析和检测内部人员的可疑行为。这些来源包括网络日志和用户活动日志。通过检查这些数…...

内网渗透-跨域环境渗透-1

目录 smbclient工具 mimikatz工具 Kerbers协议 NTLM认证 hash传递攻击&#xff08;PTH攻击&#xff09; 黄金票据攻击 白银票据 MS14-068 smbclient工具 在linux里面连接远程windows共享目录&#xff0c;可以使用这个工具 ​ 第一种连接方式&#xff1a;smbclient -L 目…...

安信可IDE(AiThinker_IDE)编译ESP8266工程方法

0 工具准备 AiThinker_IDE.exe ESP8266工程源码 1 安信可IDE&#xff08;AiThinker_IDE&#xff09;编译ESP8266工程方法 1.1 解压ESP8266工程文件夹 我们这里使用的是NON-OS_SDK&#xff0c;将NON-OS_SDK中的1_UART文件夹解压到工作目录即可 我这里解压到了桌面&#xff0c…...

【java数据结构】HashMap和HashSet

目录 一.认识哈希表&#xff1a; 1.1什么是哈希表&#xff1f; 1.2哈希表的表示&#xff1a; 1.3常见哈希函数&#xff1a; 二.认识HashMap和HashSet: 2.1关于Map.Entry的说明:,> 2.2Map常用方法说明&#xff1a; 2.3HashMap的使用案例&#xff1a; 2.4Set常见方法…...

基于Springboot的高校汉服租赁网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的高校汉服租赁网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…...

分布式解决方案

目录 1. 分布式ID1-1. 传统方案1-2. 分布式ID特点1-3. 实现方案1-4. 开源组件 2. 分布式Session2-1. 传统Session2-2. Spring-Session2-3. Token Redis2-4. JWT2-5. 拦截器统一处理Token2-6. Oauth2 3. 分布式锁3-1. redis3-2. Zookeeper 1. 分布式ID 1-1. 传统方案 时间戳U…...

力扣刷题日记——L724. 寻找数组的中心下标

1. 前言 今天是力扣刷题日记的第二天&#xff0c;今天依旧是一道简单题啊&#xff0c;慢慢来&#xff0c;先看看题目是什么吧。 2. 题目描述 给你一个整数数组 nums &#xff0c;请计算数组的 中心下标。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和…...

【Kotlin】类和对象

1 前言 Kotlin 是面向对象编程语言&#xff0c;与 Java 语言类似&#xff0c;都有类、对象、属性、构造函数、成员函数&#xff0c;都有封装、继承、多态三大特性&#xff0c;不同点如下。 Java 有静态&#xff08;static&#xff09;代码块&#xff0c;Kotlin 没有&#xff1…...

Docker完整版(一)

Docker完整版&#xff08;一&#xff09; 一、Docker概述1.1、Docker简介1.2、Docker的用途1.3、容器与虚拟机的区别1.4、Docker系统架构1.5、Docker仓库 二、Docker引擎2.1、Docker引擎架构2.2、Docker引擎分类2.3、Docker引擎的安装2.4、Docker镜像加速器 三、Docker镜像3.1、…...

AIOPS:Zabbix结合讯飞星火做自动化告警+邮件通知并基于人工智能提供解决方案

目前Zabbix官方已经提供Zabbix+ChatGPT的解决方案 ChatGPT一周年,你充分利用了吗?Zabbix+ChatGPT,轻松化解告警! 但是由于需要魔法等其他因素,比较不稳定,遂决定使用国内模型,这里我挑选的是讯飞星火,基于我之前的文档,在此基础上通过Zabbix的告警脚本实现调用AI模型…...

AHU 汇编 实验六

一、实验名称&#xff1a;实验6 输入一个16进制数&#xff0c;把它转换为10进制数输出 实验目的&#xff1a; 培养汇编中设计子程序的能力 实验过程&#xff1a; 源代码&#xff1a; data segmentbuff1 db Please input a number(H):$buff2 db 30,?,30 dup(?),13,10buff3 …...

Linux的输出、输入重定向和管道

目录 输出重定向 输入重定向 < << 管道操作 输出重定向 当我输⼊⼀个命令之后&#xff0c;回⻋&#xff0c;命令产⽣了结果&#xff0c;结果默认是输出到屏幕上的。 默认情况&#xff0c;⽆论⼀个命令执⾏正确与否&#xff0c;结果都会默认输出到屏幕上。 在有…...

java-新手笔记(枚举)

枚举&#xff08;Enumeration&#xff09;是一种特殊的类&#xff0c;用于表示固定数量的常量值。 枚举类型使得代码更加清晰&#xff0c;易于维护&#xff0c;同时也增加了类型安全。 这边使用一个枚举封装重要数据 enum Day {SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FR…...

Centos7 安装postgresql14后无法连接数据库

1、数据库服务器允许外部访问5432端口。 2、postgresql.conf 3、pg_hba.conf a、制定某个IP&#xff08;192.168.0.107&#xff09;访问 b、指定ip段访问 允许10.1.1.0~10.1.1.255网段登录数据库 host all all 10.1.1.0/24 trust c、指定全网访问 host a…...

GaussDB(DWS)运维利刃:TopSQL工具解析

在生产环境中&#xff0c;难免会面临查询语句出现异常中断、阻塞时间长等突发问题&#xff0c;如果没能及时记录信息&#xff0c;事后就需要投入更多的人力及时间成本进行问题的定位和解决&#xff0c;有时还无法定位到错误出现的地方。在本期《GaussDB(DWS)运维利刃&#xff1…...

信息安全、网络安全以及数据安全三者之间的区别

随着信息技术的飞速发展&#xff0c;网络安全、信息安全、数据安全等词汇在平时出现的频率越来越高&#xff0c;尤其是数据安全&#xff0c;是大家都关心的一个重要话题。事实上&#xff0c;有很多人对网络安全、信息安全、数据安全的概念是区分不清的&#xff0c;下面由我帮大…...

电解除湿器ROSAHL (电解质膜)的工作原理是什么?电解除湿器推荐?

ROSAHL电解除湿器的核心是固态聚合物电解质&#xff08;SPE&#xff09;膜技术&#xff0c;这是一种通过电化学反应实现除湿的创新方法&#xff0c;它的工作原理可以用"三步走"来概括&#xff1a;① 电解捕获&#xff1a;在3V直流电作用下&#xff0c;除湿器内侧的水…...

TI F28P65X开发板实战:CPU Timer精准定时与LED控制

1. 从零开始玩转F28P65X定时器 第一次接触TI的F28P65X开发板时&#xff0c;我被它强大的定时器功能惊艳到了。这块芯片内置的CPU Timer精度可以达到微秒级&#xff0c;对于需要精确时间控制的场景简直是神器。就拿最简单的LED闪烁来说&#xff0c;传统延时函数控制闪烁间隔总会…...

别再只写静态页面了!鸿蒙Next通讯录开发中,SQLite数据库的增删改查实战避坑指南

鸿蒙Next通讯录开发实战&#xff1a;SQLite数据库操作与UI联动的深度解析 第一次在鸿蒙Next上尝试把通讯录UI和数据库绑定时&#xff0c;我盯着那个空荡荡的List组件发呆了半小时——明明数据已经插入成功了&#xff0c;为什么界面就是不刷新&#xff1f;这个问题困扰了无数刚接…...

OpenClaw学术利器:Phi-3-vision-128k自动批改作业与生成错题集

OpenClaw学术利器&#xff1a;Phi-3-vision-128k自动批改作业与生成错题集 1. 为什么需要自动化作业批改系统 作为一名经常需要批改大量作业的教育工作者&#xff0c;我深知手工批改的痛点。每次面对堆积如山的作业本&#xff0c;不仅耗时费力&#xff0c;还难以系统性地记录…...

让 ABAP 编码更顺手:全面掌握 ADT 中的预测式代码补全

在现代 ABAP 开发里,代码补全早已不只是 Ctrl + Space 之后弹出一个候选列表那么简单。随着 SAP 在 ADT,也就是 ABAP development tools for Eclipse 中持续引入 AI 辅助能力,Predictive Code Completion 已经从传统补全的补充工具,逐步变成很多开发者日常写代码时的隐形助…...

手把手教你用立创EDA搞定蓝桥杯十五届省赛真题PCB:从元器件布局到差分对走线详解

立创EDA实战&#xff1a;蓝桥杯PCB设计竞赛全流程拆解 参加蓝桥杯EDA竞赛的同学们常常面临一个核心挑战&#xff1a;如何在有限时间内完成既符合电气特性又具备竞赛美学的PCB设计。作为连续三年担任蓝桥杯EDA组指导的技术顾问&#xff0c;我发现90%的参赛者在差分对处理、电源模…...

R语言中的loess函数:从原理到实战时序数据分析

1. 理解loess回归&#xff1a;从数学原理到生活场景 第一次接触loess函数时&#xff0c;我盯着金融数据里那些弯弯曲曲的折线图发愁——传统的线性回归画出来的直线根本抓不住股价的波动规律。这就像用直尺画蒙娜丽莎的微笑&#xff0c;技术没错&#xff0c;但完全不对味。loes…...

2026 年用 AI 赚钱的 5 条真实路径,哪条适合开发者?

点击上方 前端Q&#xff0c;关注公众号回复加群&#xff0c;加入前端Q技术交流群如果你想系统地学习AI&#xff0c;推荐一波我的2个合集&#xff0c;Harness Engineering&#xff1a;把Agent系统化和AI 概念科普。这几个月 AI 赚钱的信息太多了&#xff0c;小红书刷三屏有两屏在…...

GoJieba词性标注功能实战:从基础用法到高级配置

GoJieba词性标注功能实战&#xff1a;从基础用法到高级配置 【免费下载链接】gojieba "结巴"中文分词的Golang版本 项目地址: https://gitcode.com/gh_mirrors/go/gojieba GoJieba作为"结巴"中文分词的Golang版本&#xff0c;提供了强大的中文处理能…...

像素幻梦视觉系统拆解:#e3f2fd像素蓝UI设计与物理反馈机制

像素幻梦视觉系统拆解&#xff1a;#e3f2fd像素蓝UI设计与物理反馈机制 1. 像素幻梦创意工坊概述 Pixel Dream Workshop&#xff08;像素幻梦创意工坊&#xff09;是一款基于FLUX.1-dev扩散模型的像素艺术生成工具。与传统AI绘图工具不同&#xff0c;它采用了独特的16-bit现代…...