后台开发核心技术与应用实践看书笔记(一):C++编程常用技术

C++编程常用技术

  • 第一个C++程序
  • 函数
    • 函数模板
  • 数组
    • 字符数组
  • 指针
    • 概念
    • 数组与指针
    • 字符串与指针
    • 函数与指针
  • 引用
    • 引用作为参数
    • 常引用
  • 结构体,公用体,枚举
    • 共用体
    • 枚举
    • 结构体,共用体在内存单元占用字节数的计算
  • 预处理
    • 常用宏定义命令
    • do while(0)的妙用
    • 条件编译
    • extern C块的应用

第一个C++程序

#include<iostream>

第一句不是C++语句,是一个预处理语句,编译器的预处理器把输入输出流的标准头文件包括在本程序中,所以不需要在句末加分号;

include一个文件,就是把这个文件的所有内容都加进来。

#include<>常用来包含系统提供的头文件,编译器会到保存系统标准头文件的位置查找头文件;

#include""常用于包括程序员自己编号的头文件,用这种格式时,编译器先查找当前目录是否有指定名称的头文件,然后从标准头目录中进行查找

当使用<iostream.h>时,相当于在C中调用库函数,使用的是全局命名空间。

不是<string.h>的升级版

命名空间是为了让大家类名共存而不至于引起冲突而设计的。C++标准函数库的所有元素都被声明在一个命名空间中,即std。

注意,最好不要在头文件中使用命名空间,否则容易造成命名冲突。

函数

函数模板

建立一个通用函数,函数类型和形参不具体指定,用一个虚拟类型代替。

调用时,系统根据实参类型来取代虚拟类型。

定义函数模板的一般格式是

template<typename T>

例子

#include<iostream>
using namspace std;
template<typename T>
T min(T a,T b,T c){if(a>b)a=b;if(a>c)a=c;return a;
}
int main(){int a=1,b=2,c=3;cout<<min(a,b,c)<<endl;long long a1=1000,b1=2000,c1=3000;cout<<min(a1,b1,c1)<<endl;return 0;
}

比起函数重载,只适用于函数个数相同而类型不同的情况。

数组

字符数组

C++用’\0’来标识一个字符串的结束。。

strlen与sizeof的区别如下

  • 前者参数必须是字符型指针char *,且必须是以’\0’结尾的,数组名作为参数传入时,已经退化为指针了。功能返回字符串长度。
  • sizeof在编译时就计算好了,计算数据空间的字节数。sizeof常用于返回类型和静态分配的对象,结构或数组所占的空间,返回值跟对象,结构,数组所存储的内容没有关系。

例子

char a[10]="helo";
char *str="hello";
sizeof(a);//为10
sizeof(str);//指针所占大小,即4。

任意类型的指针都占4个字节。

还可以sizeof(函数名),即函数返回类型的空间大小,返回类型不能是void。

指针

概念

程序经过编译以后已经将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。比如int a=4变量这种

数组与指针

C++中,数组名代表数组第一个元素的地址,如下程序定义了两个变量:

int *p;
int a[10];

若p=a等价于p=&a[0]

数组指针,也称行指针(是一个指针变量,专门指向二维数组的)

假设定义int (*p)[n],p+1时,p要跨过n个整型数据的长度。

例子

int a[3][4];
int (*p)[4];
p=a;//将二维数组的首地址赋给p,也就是a[0]或&a[0][0];
p++; //执行后,p跨过行a[0][],指向了行a[1][]

指针数组。(多个指针变量)

int *p[n];这是一个整型指针数组,它有n个指针类型的数组元素。

这里P+1,P=a这些操作都是错的,因为p是个不可知的表示。

只有p[0],p[1]这些指针变量用来存放变量地址。

可以这样*p=a赋值这里 *p表示指针数组第一个元素的值,a的首地址的值。

二维数组赋给一指针数组

int *p[3];
int a[3][4];
for(int i=0;i<3;++i)
{p[i]=a[i];
}

表示数组中第i行j列一个元素

*(p[i]+j)

*( *(p+i)+j)

(*(p+i))[j]

其中优先级()>[]>*

字符串与指针

char *str1="abc";//abc是常量被放到程序的常量区,不能被修改。string str="abc";
char str2[]="abc";

字符串指针变量存放首地址可以改变指向不同的字符串,但是不能改变所指向的字符串常量。

后两者都有单独的连续存储空间。

函数与指针

每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址,有了指向函数的指针变量后,就可以用该指针变量调用函数了。

函数指针声明方法举例

int func(int a);
int (*f)(int a);//*的括号不能省略
f=&func;(*f)(10)//这样就调用了

引用

用于为一个变量起一个别名。

函数执行期间,不可以把一个应用再作为其他变量的引用。

引用作为参数

将一般变量作为函数的参数,传给形参的是变量的值,传递是单向的。

如果在执行函数期间形参的值发生变化,并不传回给实参。

因为在调用函数时,形参和实参不是同一个存储单元。

使用引用传递函数的参数时,在内存中并没有产生实参的副本,而是对实参直接操作。

当使用一般变量传递函数的参数时,当函数发生调用时,需要给形参分配存储单元,形参变量是实参变量的副本。

如果传递的是对象,还将调用拷贝构造函数。

所以当函数参数较大时,用引用效果更好。

使用指针达到同样效果,但是还是要给形参分配存储单元

常引用

要提高程序效率,又要数据不能被改变,就用常引用。

普通引用不能指向常量。

能用const引用就尽量用const引用。

结构体,公用体,枚举

共用体

用关键字union定义,可以定义多种不同的数据类型,里面的数据共享一段内存,不同时间里保存不同的数据类型的长度的变量,以节省空间。

但同一时间只能存储其中一个成员变量的值。

0x意思是十六进制数

可以使用union判断系统是大端还是小端存储。代码如下

#include<iostream>
using namespace std;
union TEST{short a;char b[sizeof(short)];
};
int main(){TEST test;test.a=0x0102;if(test.b[0]==0x01&&test.b[1]==0x02)cout<<"大端"<<endl;else if(test.b[0]==0x02&&test.b[1]==0x01)cout<<"small endian."<<endl;return 0;
}

小端符合人的感受。高位存高地址。

16进制转2进制即4位,0x01,即8位二进制,也就是一个字节。

几乎所有网络协议都是采用big endian的方式来传输数据的,当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换称为网路字节序后再进行传播。

枚举

实际问题中,有些变量的取值被限定在一个有限的范围内。

枚举类型是一种基本类型,不是构造类型,因为它不能再分解为任何其他基本类型。

声明方式

enum weekday{sun,mou,tue,wed,thu,fri,sat}
//定义变量
enum weekday a,b,c;//或者
enum weekday{sun,mou,tue,wed,thu,fri,sat}a,b,c;
//或者
enum {sun,mou,tue,wed,thu,fri,sat}a,b,c;

枚举值是常量不是变量,不能在程序中用赋值语句再对它赋值。

错误用法

sun=5;
mon=2;
sun=mon;

只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。

a=sum;
b=mon;//正确//错误;
a=0;
b=1;

默认第一个枚举值为0

默认枚举值为前面加1

结构体,共用体在内存单元占用字节数的计算

float4字节

union的字节数计算

union A{int a[5];char b;double c;
};
int main(){cout<<sizeof(A)<<endl;return 0;
}

打印24个字节。

union变量共用内存,应以最长的为准,但是结果却不是4*5=20个字节,因为还需要以union内最长的变量进行默认对齐。

double8字节,要对齐就只能24了。

把int a[5]编程inta[7],那么对齐结果又变成32.

struct字节数计算

struct B
{char a;double b;int c;
};
int main()
{cout<<sizeof(B)<<endl;return 0;
}

打印出来24

char偏移量0,占用1字节,然后补齐7字节,达到double对齐,double占用8字节,现在偏移量是16字节,int可以直接存储,占用4字节。现在总共就是20字节。

但是它还不是结构体内最长的空间类型的字节数的倍数,这里就是需要达到double8字节的倍数,即24。
混合结构体大小的计算

typedef union{long i;int k[5];char c;
}UPDATE;
struct data{int cat;UPDATE cow;double dog;
}too;UDATE temp;
int main()
{cout<<sizeof(struct data)+sizeof(temp)<<endl;
}

64为机器运行执行结果是40+24即64。

同理temp是24字节,然后struct就是4+24+8=36,还需要与8对齐,那么就是40字节。

预处理

主要4中预处理:宏定义,文件包含,条件编译和布局控制。

常用宏定义命令

#define用来将一个标识符(宏名)定义为一个字符串(替换文本)。

在简单宏定义的使用中,当替换文本所表示的字符串是一个表达式时,需要加上括号,否则容易引起误解和误用。

比如

#define N 2+9
int main()
{int a=N*N;cout<<a<<endl;return 0;
}

因为宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生,在展开时是在宏N出现的地方只是简单地使用串2+9来代替N,并不会增添任何的符号。所以该程序展开后的结果是a=2+9*2+9,计算后的结果为29。实际上本意可能是11 *11=121

带参数的宏定义的声明格式如下所示:

#define 宏 (参数表列) 宏

例:#define A(x) x

#define area(x) x*x

这样的话可能出现问题

比如调用者

int y=area(2+2);

那么结果就是2+2*2+2。为8,本意可能是4 *4=16

初步解决

#define area(x) (x)*(x)

但是调用还可能是

int y=area(2+2)/area(2+2);

那么结果就是(2+2)*(2+2)/(2+2) *(2+2),结果是16

完整版解决应该是

#define area(x) ((x)*(x))

do while(0)的妙用

假设一个宏

#define Foo(x) {\statement one;\statement two;\
}

然后假设代码这样写

if(condition)Foo(x);
else...;

那么展开就是

if(condition)statement one;statement two;
else...;

这样else就没能和if连在一起,编译错误了

而这样使用

#define Foo(x) do{\statement one;\statement two;\
}while(0)

展开就是

if(condition)do{statement one;statement two;}while(0)
else...;

这样就没问题,因为do while(0)相当于单个语句。

条件编译

常见形式

#ifdef 标识符程序段1#else程序段2#endif

作用:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。else部分也可以没有。

另外形式

#if 表达式程序段1#else程序段2#endif

作用:当指定的表达式值为真(非零)时就编译程序段1,否则编译程序段2。

这里程序段既可以是语句组,也可以是命令行。

extern C块的应用

#ifdef __cplusplusextern "C"{
#endif....
}
#ifdef __cplusplus
}
#endif

__cplusplus是C++的预定义宏,表示当前开发环境是C++

C++为了支持重载,在编译生成的汇编代码中,会对函数名字进行一些处理(通常称为函数名字改编),如加入函数的参数类型或返回类型等,而在C语言中,只是简单地函数名字而已,如下所示:

int func(int a);
int func(double a);

C语言无法区分上面两个函数的不同,因为C编译器产生的函数名都是_func,而C++编译器产生的名字则可能是_func_Fi和_func_Fd,这样就很好的把函数区分开了。

作用:告诉C++编译器这段代码要按C标准编译,以尽可能地保持C++与C的兼容性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/99381.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【gitlab】从其他仓库创建项目

需求描述 解决方法 以renren-fast脚手架为例 第一步 第二步 第三步 第四步 参考文章

【面试】pc寄存器题

目录 1.使用pc寄存器存储字节码指令地址有什么作用&#xff1f;&#xff08;为什么使用pc寄存器记录当前线程的执行地址&#xff1f;&#xff09;2.pc寄存器为什么被设定为线程私有的&#xff1f; 1.使用pc寄存器存储字节码指令地址有什么作用&#xff1f;&#xff08;为什么使…

应用层协议 HTTP

一、应用层协议 我们已经学过 TCP/IP , 已然知道数据能从客户端进程经过路径选择跨网络传送到服务器端进程。 我们还需要知道的是&#xff0c;我们把数据从 A 端传送到 B 端&#xff0c; TCP/IP 解决的是顺丰的功能&#xff0c;而两端还要对数据进行加工处理或者使用&#xf…

算法-二叉树

1. 二叉树定义 二叉树是一种常见的树状数据结构&#xff0c;它由节点组成&#xff0c;每个节点最多有两个子节点&#xff0c;通常称为左子节点和右子节点。二叉树的定义如下&#xff1a; 节点&#xff08;Node&#xff09;&#xff1a;每个节点包含一个数据元素&#xff08;通…

python常用库之数据库orm框架之SQLAlchemy

文章目录 python常用库之数据库orm框架之SQLAlchemy一、什么是SQLAlchemySQLAlchemy 使用场景 二、SQLAlchemy使用SQLAlchemy根据模型查询SQLAlchemy SQL 格式化的方式db_session.query和 db_session.execute区别实测demo 总结&#xff1a;让我们留意一下SQLAlchemy 的 lazy lo…

SpringMVC的视图

文章目录 1. ThymeleafView2. 转发视图3. 重定向视图4. 视图控制器view-controller5. 总结6. 荐书 SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户SpringMVC视图的种类很多&#xff0c;默认有转发视图和重定向视图 当工…

二维反射容斥:P9366

https://www.luogu.com.cn/problem/P9366 构造循环矩阵&#xff0c;考虑反射容斥和将军饮马 考虑二维不太好做&#xff0c;我们曼哈顿距离转切比雪夫距离&#xff0c;变成一维的情况。 由于棋盘是正方形的&#xff0c;所以循环长度为 2 n 4 2n4 2n4。用多项式快速幂预处理&…

el-cascader

场景&#xff1a; el-cascader lazy multiple 反显数据 非lazy的场景 selecetedOptions2: [[1, 2, 3],[1, 2, 4], ],可以正常回显&#xff1b;> ok lazy场景下&#xff1a; 是不可以回显的… 如果el-cascader是异步的单选 cascader默认会加载下个层级的&#xff08;子…

Unity设计模式——原型模式

原型模式&#xff08;Prototype&#xff09;用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象再创建另外一个可定制的对象&#xff0c;而且不需知道任何创建的细节 。 原型类 Prototype&#xff1a; abstract class P…

十一、2023.10.5.计算机网络(end).11

文章目录 17、说说 TCP 可靠性保证&#xff1f;18、简述 TCP 滑动窗口以及重传机制?19、说说滑动窗口过小怎么办?20、说说如果三次握手时候每次握手信息对方没收到会怎么样&#xff0c;分情况介绍&#xff1f;21、简述 TCP 的 TIME_WAIT&#xff0c;为什么需要有这个状态&…

虚拟机机初始化配置

虚拟机信息 镜像&#xff1a;Centos7 模板机配置&#xff1a;4U4G 100G存储 /boot 800MB /swap 物理内存如果低于2G&#xff0c;设定为虚拟内存设定为物理内存2倍&#xff0c;物理内存高于2G设定为4G。 / 95.2G 虚拟机安装完成后配置网卡 [rootlocalho…

ctfshow-web5(md5弱比较)

打开题目链接是html和php代码 html没啥有用信息&#xff0c;这里审一下php代码 &#xff1a; 要求使用get方式传入两个参数 v1&#xff0c;v2 ctype_alpha()函数&#xff1a;用于检查给定的字符串是否仅包含字母&#xff1b; is_numeric()函数&#xff1a;检测字符串是否只由…

聊聊分布式架构05——[NIO基础]BIO到NIO的演进

目录 I/O I/O模型 BIO示例 BIO与NIO比较 NIO的三大核心 NIO核心之缓冲区 Buffer常用子类&#xff1a; Buffer常用API Buffer中的重要概念 NIO核心之通道 FileChannel 类 FileChannel常用方法 NIO核心之选择器 概述 应用 NIO非阻塞原理分析 服务端流程 客户端…

请求的转发和重定向

RequestDispatcher接口实现转发&#xff1a; jsp1上链接到Servlet&#xff0c;Servlet再转发&#xff08;关键在这里怎么实现转发&#xff1f;&#xff1f;&#xff09; 演示index.html页面---->Servlet1(转发到)------>Servlet2 实现转发流程 1.用HttpServletReques…

如何解决openal32.dll丢失,有什么办法解决

你第一次知道openal32.dll文件是在什么情况下&#xff0c;你了解过openal32.dll文件吗&#xff1f;如果电脑中openal32.dll丢失有什么办法可以解决&#xff0c;今天就教大家如何解决openal32.dll丢失&#xff0c;都有哪些办法可以解决openal32.dll丢失。 一&#xff0e;openal3…

Mac下docker安装MySQL8.0.34

学习并记录一下如何用docker部署MySQL 在Docker中搜索并下载MySQL8.0.x的最新版本 下载好后&#xff0c;在Images中就可以看到MySQL的镜像了 通过下面的命令也可以查看docker images启动镜像&#xff0c;使用下面的命令就可以启动镜像了docker run -itd --name mysql8.0.34 -…

2021年03月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 对于字典infor {“name”:“tom”, “age”:13, “sex”:“male”}&#xff0c;删除"age":13键值对的操作正确的…

蓝桥杯每日一题2023.10.9

题目描述 成绩统计 - 蓝桥云课 (lanqiao.cn) 题目分析 学会使用四舍五入函数round #include<bits/stdc.h> using namespace std; int s1, s2; int main() {int n, x;cin >> n;for(int i 1; i < n; i ){cin >> x; if(x > 60)s1 ;if(x > 85)s2 ;…

C语言练习百题之插入一个数

题目:有一个已经排好序的数组。现输入一个数&#xff0c;要求按原来的规律将它插入数组中。 程序分析 要将一个数插入已经排好序的数组中&#xff0c;我们可以采用以下步骤&#xff1a; 遍历数组&#xff0c;找到第一个大于待插入数的位置。将待插入数插入到该位置&#xff…

关于一篇ElementUI之CUD+表单验证

目录 一.CUD增删改查简述 1.1.增删改功能实现 二.表单验证 前端所有代码&#xff1a; 好啦今天就分享到这了&#xff0c;希望能帮到你哦&#xff01;&#xff01;&#xff01; 以下的代码基于我博客中的代码进行续写 : 关于ElementUI之动态树数据表格分页实例 一.CUD增删改…