【C++进阶】一些小知识点

news/2024/4/25 5:10:53/文章来源:https://blog.csdn.net/weixin_43912621/article/details/129110334

const限定符

用const给字面常量起个名字(标识符),这个标识符就称为标识符常量;因为标识符常量的声明和使用形式很像变量,所以也称常变量。声明方式:

const int a = 77;
const float PI = 3.14159f;

需要注意的是,常量必须在定义时初始化,初始化常量不能重新被赋值。

关于指针,

const int * p;

const在左边,这表示我们定义了一个指针,指向的数据类型为const int,即p是一个常量。

int a = 77;
int * const p = &a;

const在*右边,表示p是一个地址常量,必须对p 进行赋值。

const定义的常量与#define定义的符号常量的区别:
1.const定义的常量有类型,而#define定义的没有类型,编译可以对前者进行类型安全检查,而后者仅仅只是做简单替换;
2.const定义的常量在编译时分配内存,而#define定义的常量是在预编译时进行替换,不分配内存。
3.作用域不同,const定义的常变量的作用域为该变量的作用域范围。而#define定义的常量作用域为它的定义点到程序结束,当然也可以在某个地方用#undef取消。

定义常量还可以用enum,高层次编程尽量用const、enum、inline替换#define定义常量。在底层编程,#define是很灵活的。

结构体内存对齐

内存对齐:编译器为每个“数据单元”按排在某个合适的位置上。C、C++语言非常灵活,它允许你干涉“内存对齐”。
为什么要对齐?性能原因:在对齐的地址上访问数据块。
如何对齐:
第一个数据成员放在offset为0的位置;
其它成员对齐至min(sizeof(member),#pragma pack所指定的值)的整数倍。#pragma pack为编译器预设的一个对齐数;
整个结构体也要对齐,结构体总大小对齐至各个成员中最大对齐数的整数倍。

举个例子:

#include <iostream>
using namespace std;struct Test{char a;double b;char c;
};int main() {Test test;cout<<sizeof(test);return 0;
}

输出为24。a在offset为0的位置。#pragma pack默认为8,double类型占8个字节,对齐数取两者最小值为8,所以b对齐至8,占offset为8~15的8个字节。c对齐至16,结构体总大小对齐至各个成员中最大对齐数的整数倍,也就是8,所以整个结构体大小为24。

下面我们将编译器默认的对齐数改为4,

#include <iostream>
using namespace std;#pragma pack(4)
struct Test{char a;double b;char c;
};
#pragma pack()int main() {Test test;cout<<sizeof(test);return 0;
}

输出结果为16。a在offset为0的位置。#pragma pack为4,double类型占8个字节,对齐数取两者最小值为4,所以b对齐至4,占offset为4~11的8个字节。c对齐至12,结构体总大小对齐至各个成员中最大对齐数的整数倍,也就是16,所以整个结构体大小为16。

域运算符

C++中增加的作用域标识符::用于对与局部变量同名的全局变量进行访问,或者用于表示类的成员。举个例子:

#include <iostream>
using namespace std;int var = 100; int main() {int var = 50;cout<<var<<endl;cout<<::var<<endl;return 0;
}

输出结果为:
在这里插入图片描述

new、delete运算符

new运算符可以用于创建堆空间,成功返回首地址,失败抛出异常。声明方式:

#include <iostream>
using namespace std;int main(){int* p = new int;//分配一个整数空间,4字节int* pt = new int(77);//初始化为77,分配一个整数空间,4字节 int* p2 = new int [50];//分配连续的50个整数空间,200字节delete p;delete pt;delete[] p2; return 0;
}

new一个新对象,首先进行内存分配(operator new),然后调用构造函数。delete释放一个对象,首先调用析构函数,然后进行释放内存(operator delete)。

重载

相同的作用域,如果两个函数名称相同,而参数不同,我们把它们称为重载overload。函数的重载又称为函数的多态性。
函数重载的不同形式有:
1.形参数量不同;
2.形参类型不用;
3.形参的顺序不同;
4.形参数量和形参类型都不同。
调用重载函数时,编译器通过检查实际参数的个数、类型和顺序来确定相应的被调用函数。
举个例子:

#include <iostream>
using namespace std;void fun(int a,int b){cout<<"int fun"<<endl;
} void fun(double a,double b){cout<<"double fun"<<endl;
}
int main() {fun(3,4);fun(3.3,4.4);return 0;
}

如果返回类型不同而函数名相同、形参也相同,则是不合法的,编译器会报语法错误。

//合法的重载例子
int abs(int i);
long abs(long i);
double abs(double i);
//非法的重载例子
int abs(int i);
long abs(int i);
double abs(int i);

name managling

name managling这里把他翻译成名字改编。C++为了支持重载,需要进行name managling。

//合法的重载例子
int abs(int i);
long abs(long i);
double abs(double i);

比如这三个abs函数,运行时编译器会对其进行名字改编,以便对这三个abs函数进行区分。

extern “C”

extern "C"实现C与C++混合编程。

extern "C" int abs(int i);

extern "C"表示不进行名字改编,按C语言的方式来解释这个函数名,C语言不支持名字改编,也就不支持函数重载,规范使用如下:

#include <iostream>
using namespace std;#ifdef _cplusplus
extern "C"
{
#endif
void fun(int a){cout<<a<<endl;
} void fun2(double a){cout<<a<<endl;
}
#ifdef _cplusplus
}
#endifint main() {fun(7);fun2(7.7);return 0;
}

带默认形参值的函数

函数声明或者定义的时候,可以给形参赋一些默认值。调用函数时,若没有给出实参,则按指定的默认值进行工作。
函数没有声明时,在函数定义中指定形参的默认值。函数既有定义又有声明时,声明时指定后,定义就不能再指定默认值 。
默认值的定义必须遵守从右到左的顺序,如果某个形参没有默认值,则它左边的参数就不能有默认值。

void func1 (int a, double b=4.5, int c=3 ) ; //合法
void func1 (int a=1, double b, int c=3 ) ;//不合法

内联函数

当程序执行函数调用时,系统要建立栈空间,保护现场,传递参数以及控制程序执行的转移等等,这些工作需要系统时间和空间的开销。有些情况下,函数本身功能简单,代码很短,但使用频率却很高,程序频繁调用该函数所花费的时间却很多,从而使得程序执行效率降低。

为了提高效率,一个解决办法就是不使用函数,直接将函数的代码嵌入到程序中。但这个办法也有缺点,一是相同代码重复书写,二是程序可读性往往没有使用函数的效果好。

为了协调好效率和可读性之间的矛盾,C++提供了另一种方法,即定义内联函数,方法是在定义函数时用修饰词inline。

内联函数与带参数宏区别

内联函数调用时,要求实参和形参的类型一致,另外内联函数会先对实参表达式进行求值,然后传递给形参;而宏调用时只用实参简单地替换形参。

内联函数是在编译的时候、在调用的地方将代码展开的,而宏则是在预处理时进行替换的。

在C++中建议采用inline函数来替换带参数的宏。

#include <iostream>
using namespace std;inline int max(int a,int b){return a > b ? a : b;
}#define MAX(a,b)((a)>(b)?(a):(b))int main() {int a = 1;int b = 2;cout<<max(a,b)<<endl;cout<<MAX(a,b)<<endl;return 0;
} 

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

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

相关文章

算法设计与分析期末考试复习(二)

分治法 将一个难以直接解决的大问题&#xff0c;分割成一些规模较小的相同问题&#xff0c;以便各个击破&#xff0c;分而治之。最好使子问题的规模大致相同。 分解&#xff08;Divide&#xff09;&#xff1a;将一个难以直接解决的大问题&#xff0c;分割成一些规模较小的子…

【拿好了!Linux 运维必备的 13 款实用工具!】

​本文介绍几款 Linux 运维比较实用的工具&#xff0c;希望对 Linux 运维人员有所帮助。 查看进程占用带宽情况 – Nethogs Nethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽。 下载&#xff1a; http://sourceforge.net/projects/nethogs/files/ne…

ZYNQ双核处理器独立运行AMP

一、简介多核处理器从多核的结构上是否一致&#xff0c;分为两种基本架构&#xff1a;同构多核架构和异构多核架构。同构多核处理器是指系统中的处理器在结构上是相同的&#xff1b;而异构处理器是指系统中的处理器在结构上是不同的&#xff0c;这些处理器可以是通用处理器&…

pyqt5通过CANoe COM Server来操作CANoe仿真工程

文章目录前言一、COM接口技术二、UI界面设计三、功能实现四、工程运行测试前言 继续学习《CANoe开发从入门到精通》。 今天在《CANoe仿真工程开发》的基础上&#xff0c;开发实现pyqt5应用程序来操控CANoe工程。 一、COM接口技术 COM&#xff08;Component Object Model&…

vue-cli引入wangEditor、Element,封装可上传附件的富文本编辑器组件(附源代码直接应用,菜单可调整)

关于Element安装引入&#xff0c;请参考我的另一篇文章&#xff1a;vue-cli引入Element Plus&#xff08;element-ui&#xff09;&#xff0c;修改主题变量&#xff0c;定义全局样式_shawxlee的博客-CSDN博客_chalk variables 1、安装wangeditor npm i wangeditor --savewangE…

【OpenFOAM】-olaFlow-算例10-wavemakerTank

算例路径&#xff1a; olaFlow\tutorials\wavemakerTank 算例描述&#xff1a; 采用 Flap和Piston两种方式的动网格进行造波 学习目标&#xff1a; 了解 olaDyMFlow 的使用&#xff1b;理解动网格使用和参数设置&#xff0c;理解 dynamicMotionSolverFvMesh 参数设置&#xff1…

【华为OD机试模拟题】用 C++ 实现 - 环中最长子串(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【Linux修炼】14.磁盘结构/文件系统/软硬链接/动静态库

每一个不曾起舞的日子&#xff0c;都是对生命的辜负。 磁盘结构/文件系统/软硬链接/动静态库前言一.磁盘结构1.1 磁盘的物理结构1.2 磁盘的存储结构1.3 磁盘的逻辑结构二.理解文件系统2.1 对IO单位的优化2.2 磁盘分区与分组2.3 分组的管理方法2.4 文件操作三.软硬链接3.1理解硬…

vue手写日历

<template><div class"page">输入月份数字<input v-model"inputVal" type"text"><button click"change">点击</button><ul class"calendar"><li class"header">{{new …

记忆总掉线?这些行为太伤脑!

人体老化过程中&#xff0c;记忆力的衰退不可避免&#xff0c;这种属于“良性”的记忆衰退。但非“良性”的记忆衰退可要重视&#xff0c;很可能是痴呆症的早期征兆。由于各种原因&#xff0c;我们各种熬夜。作息的不规律扰乱大脑神经系统的调节。这种长期慢性损害大脑&#xf…

WebDAV之π-Disk派盘+Cloud Player

Cloud Player 支持WebDAV方式连接π-Disk派盘。 推荐一款云媒体播放器是存储在常见云平台中的内容的通用播放器。 Cloud Player云媒体播放器是存储在常见云平台中的内容的通用播放器,无需将其下载到设备。支持以下云平台:Google Drive、DropBox、One Drive、WebDav等。此外,…

超纯水制备,MB-106UP抛光树脂的技术解析

超纯水&#xff08;Ultrapure water&#xff09;又称UP水&#xff0c;是指电阻率达到18 MΩ*cm&#xff08;25℃&#xff09;的水。这种水中除了水分子外&#xff0c;几乎没有什么杂质&#xff0c;更没有细菌、病毒、含氯二噁英等有机物&#xff0c;当然也没有人体所需的矿物质…

【ArcGIS Pro二次开发】(7):地图(Map)的基本操作

地图是ArcGIS Pro中的基础起点&#xff0c;也是大多数工程的基础。主要用于显示表示空间数据的图层。 一、地图(Map)的基本操作示例 1、获取当前地图 var map MapView.Active.Map; 2、获取一级图层 var lys map.Layers; 用于获取地图中的单一图层&#xff0c;以及图层组…

深入了解Java线程锁(一)

在上一篇《如何保证线程的原子性》中&#xff0c;我们谈到了锁&#xff08;Synchronized&#xff09;&#xff0c; 这次我们就来深入探讨一下Java多线程中的锁。 互斥锁的本质是共享资源。 如上图所示&#xff0c; Thread1访问受保护资源&#xff0c;对其加锁&#xff0c;将…

【GO】k8s 管理系统项目16[前端部分–前端布局]

【GO】k8s 管理系统项目[前端部分–前端布局] 1. 前端布局 2. Layout 2.1 layout src/layout/Layout.vue <template><div class"common-layout"><el-container><el-side width"200">Aside</el-side><el-container>…

CAN总线开发一本全(3) - 微控制器集成的FlexCAN外设

CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设 苏勇&#xff0c;2023年2月 文章目录CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设引言硬件外设模块系统概要总线接口单元 - 寄存器清单数据结构 - 消息缓冲区MB初始化过…

React(一):初识React、类组件、jsx的基础语法

React&#xff08;一&#xff09;一、初识React1.简单介绍2.React的三个依赖3.Hello React案例二、类组件1.定义类组件并渲染2.绑定事件函数&#xff08;奇怪的this问题&#xff09;3.数组形式数据的展示&#xff08;电影案例&#xff09;4.计数器案例三、jsx语法详解1.jsx的书…

利用InceptionV3实现图像分类

最近在做一个机审的项目&#xff0c;初步希望实现图像的四分类&#xff0c;即&#xff1a;正常&#xff08;neutral&#xff09;、涉政&#xff08;political&#xff09;、涉黄&#xff08;porn&#xff09;、涉恐&#xff08;terrorism&#xff09;。有朋友给推荐了个github上…

机器学习笔记之近似推断(一)从深度学习角度认识推断

机器学习笔记之近似推断——从深度学习角度认识推断引言推断——基本介绍精确推断难的原因虽然能够表示&#xff0c;但计算代价太大无法直接表示引言 本节是一篇关于推断总结的博客&#xff0c;侧重点在于深度学习模型中的推断任务。 推断——基本介绍 推断(Inference\text{…

Python中实现将内容进行base64编码与解码

一、需求说明需要使用Python实现将内容转为base64编码&#xff0c;解码&#xff0c;方便后续的数据操作。二、base64简介Base64是一种二进制到文本的编码方式【是一种基于 64 个可打印字符来表示二进制数据的表示方法&#xff08;由于 2^664&#xff0c;所以每 6 个比特为一个单…