C++ 基础

news2024/9/27 12:14:49

命名空间

在 C/C++ 中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace 关键字的出现就是针对这种问题的。

定义

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

  1. 命名空间中可以定义变量/函数/类
  2. 命名空间可以嵌套
  3. 同一个工程中允许存在多个相同名称的命名空间,编译器会合成为一个命名空间

注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

使用方式

  1. 加命名空间名称及作用域限定符

  2. 使用 using 将命名空间中成员引入

  3. 使用 using namespace 命名空间名称引入

// 分别对应上面三种方式
// 1. std::cin
// 2. using std::cin
// 3. using namespce std

缺省参数

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

分类

  1. 全缺省参数
  2. 半缺省参数
// 分别对应上面两种形式
// 1. void test1(int a = 1, int b = 2, int c = 3)
// 2. void test2(int a, int b = 2, int c = 3)

注意:

  1. 半缺省参数必须从右往左依次给出,不能间隔
    • 一旦某个参数被赋予了默认值,它后面的所有参数都必须有默认值
  2. 缺省参数不能在函数声明和定义中同时出现
    • 在给定的作用域中一个形参只能被赋予一次默认实参
  3. 局部变量不能作为默认实参
    • 除此之外,只要表达式的类型能转化成形参所需的类型,该表达式就能作为默认实参
    • 用作默认实参的名字在函数声明所在的作用域解析,而这些名字的求值过程发生在函数调用时
// 多次声明同一个函数,为其不同参数添加默认值是合法的,但是不推荐
void test(int a, int b = 2, int c = 3);
void test(int a = 1, int b, int c);

函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

概念

函数重载:是函数的一种特殊情况,C++ 允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表参数个数类型顺序)不同,返回值不作要求,常用来处理实现功能类似数据类型不同的问题。

重载示例:

int Add(int left, int right);
long Add(long left, long right);
double Add(double left, double right);

Name Mangling

C

早期 Unix 下的 C 语言因为历史原因规定,C 语言源代码文件中的所有全局变量和函数经过编译以后,相对应的符号前加上下划线 _。在现在 Linux 下的 GCC 编译器中,默认情况已经去掉了在 C 语言符号前面加下划线的方式,而是直接使用函数名。

C 语言不支持函数重载,因为 C 语言直接使用函数名去表示和查找,而重载函数函数名相同。编译的时候,两个函数名相同的函数,在符号表中存在歧义和冲突,其在链接的时候也存在歧义和冲突。

C++

C++ 的目标文件符号表中不是直接用函数名来标识和查找函数。

g++ 的函数名修饰规则:

  • 所有的符号都以 _Z 开头,对于嵌套的名字(在名称空间或在类里面的),后面紧跟 N,然后是各个名称空间和类的名字,每个名字前是名字字符串长度,再以 E 结尾
  • 对于一个函数来说,它的参数列表紧跟在函数名 或 E 后面
  • 全局变量和静态变量也有同样的机制,不过修饰并没有使用变量类型

命名修饰

有了函数名修饰规则,只要参数列表不同,符号表存储的修饰后的函数名就不同,也就不存在二义性和冲突了。

extern “C”

有时候在 C++ 工程中可能需要将某些函数按照 C 的风格来编译,在函数前加 extern “C”,意思是告诉编译器,将该函数按照 C 语言规则来编译。

那么 C 语言的项目可以使用 C++ 编写的库吗?

是可以的,库是一种二进制文件,只要能够找到相应的函数就可以使用。若有函数重载的话,是没办法使用的。

引用

概念

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

语法:类型& 引用变量名 = 引用实体

int a = 10;
int& ra = a;

引用类型必须和引用实体同种类型的

特性

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

使用场景

  1. 做参数(提高效率,形参的改变可以影响实参)
  2. 做返回值(提高效率,修改返回变量)

注意:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

传值和传引用效率比较

以值作为参数或返回值类型,在函数传参/返回时,不会直接传递实参/将变量本身直接返回,而是传递/返回一份变量的临时的拷贝,因此用值作为参数/返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时。

指针和引用的区别

在语法概念上引用就是一个别名,没有独立空间,和其引用体公用一块空间。

在底层实现上实际是有空间的,引用是按照指针的方式来实现的

引用和指针的不同点:

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时绑定一个实体后,就不能再绑定其他实体,而指针可以改变指向
  3. 没有 NULL 引用,但有 NULL 指针
  4. 在 sizeof 中含义不同:引用结果为引用类型的大小,但指针始终是指针类型所占字节个数
  5. 有多级指针,但是没有多级引用
  6. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理

内敛函数

概念

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

特性

  1. inline 是一种以空间换时间的做法,省去调用函数额开销,增加了内存和磁盘占用,所以代码很长或者有循环/递归的函数不适宜使用作为内联函数
  2. inline 对于编译器而言只是一个请求,编译器会自动优化,如果定义为 inline 的函数体内有循环/递归等等,编译器优化时会忽略掉内联请求
  3. inline 不能将声明和定义分离,分离会导致链接错误

功能

宏的优点:

  1. 增强代码的复用性
  2. 提高性能

宏的缺点:

  1. 不方便调试宏(预处理阶段进行了替换)
  2. 导致代码可读性差,可维护性差,容易误用
  3. 没有类型安全的检查

函数定义换用内联函数

  • 在类内定义的成员函数会默认加上内敛(隐式内敛)
  • 内敛声明定义必须一起,否则不起作用

常量定义换用 const

C++ 中被 const 修饰的变量:编译器看到变量被 const 修饰,默认其不会改变,若后面有用到该变量会将其值放入寄存器中,使用时直接读取寄存器中数据,而不是到内存中读取。

  • 编译器一般不会为整数型 const 对象在内存中开辟空间,除非指针或引用等必须用它的地址的情况

  • 可以用 volatile 修饰该变量,让每次取值都必须到内存中读取

#include <iostream>
using namespace std;

int main() {
    // volatile const int a = 10;
    const int a = 10;
    int* p = (int*)(&a);
    *p = 20;
    // 此时打印 a 的值是 10, *p 的值是 20
    cout << a << " " << *p << endl;
    return 0;
}

constexpr

常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式。

一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定,例如:

const int num1 = 1230;		// num1 是常量表达式
const int num2 = num1 + 1;	// num2 是常量表达式
int num3 = 1002;		    // num3 不是常量表达式
const int num4 = GetNum();  // num4 不是常量表达式 

尽管 num3 的初始值是个字面值常量,但由于它的数据类型只是普通的 int 而非 const int,所以它不属于常量表达式。另一方面,尽管 num4 本身是一个常量,但它的具体值直到运行时才能获取到,所以也不是常量表达式。

constexpr 变量

C++ 11 新标准规定,允许将变量声明为 constexpr 类型以便编译器来验证变量的值是否是一个常量表达式。声明为 constexpr 的变量一定是一个常量,而且必须用常量表达式初始化。

constexpr int num1 = 1230;		// 1230 是常量表达式
constexpr int num2 = num1 + 1;	// num1 + 1 是常量表达式
constexpr int num3 = GetNum();	// 只有当 GetNum 是一个 constexpr 函数时,才是一条正确的声明语句

指针和引用都能定义成 constexpr,但它们的初始值却受到严格的限制。一个 constexpr 指针的初始值必须是 nullptr 或 0,或者是存储于某个固定地址中的对象。

  • 固定地址:函数体外定义的对象(全局对象)、static 修饰的对象
  • constexpr 修饰指针,只限定指针的指向不能更改,对指向空间的值不作限制

constexpr 函数

constexpr 函数(constexpr function)是指能用于常量表达式的函数。

需要遵守两个约定:

  • 函数的返回类型及所有形参的类型都得是字面值类型
  • 函数体中必须有且只有一条 return 语句

执行初始化任务时,编译器把 constexpr 函数的调用替换成其结果值。为了能在编译过程中随时展开,constexpr 函数被隐式地指定为内敛函数。constexpr 函数体内也可以包含其他语句,只要这些语句在运行时不执行任何操作就行。例如,空语句、类型别名以及 using 声明。

nullptr

由于 C++ 中 NULL 被定义成字面量 0,这样就可能回带来一些问题,因为 0 既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11 中新增了 nullptr,用于表示空指针。

//stddef.h
#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

注意:

  1. 在使用 nullptr 时,不需要包含头文件,因为 nullptr 是 C++11 新增的关键字
  2. 在 C++11 中,sizeof(nullptr)sizeof((void*)0) 所占的字节数相同
  3. 为了提高代码的健壮性,在表示指针空值时建议使用 nullptr

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

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

相关文章

就现在!为元宇宙和Web3对互联网的改造做准备!

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;8分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 如今&#xff0c;互联网是各种不同的网站、应用程序和平台的集合。由于彼此分离…

微信小程序Springboot 校园拼车自助服务系统java

系统管理员&#xff1a; 管理员账户管理&#xff1a;在线对管理员的账户信息进行管理&#xff0c;包括对管理员信息的增加修改以及密码的修改等。 站内新闻管理&#xff1a;在后台对站内新闻信息进行发布&#xff0c;并能够对站内新闻信息进行删除修改等。 论坛版块管理&#x…

SpringMVC--注解配置SpringMVC、SpringMVC执行流程

注解配置SpringMVC 使用配置类和注解代替web.xml和SpringMVC配置文件的功能 创建初始化类&#xff0c;代替web.xml 在Servlet3.0环境中&#xff0c;容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类&#xff0c; 如果找到的话就用它来配置Servle…

69. x 的平方根

文章目录题目描述二分法参考文献题目描述 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 注意&#xff1a;不允许使用任何内置指数函数和算符&#xff0c;例如 pow(x…

pwn手记录题1

fuzzerinstrospector(首届数字空间安全攻防大赛) 主体流程&#xff08;相对比较简单&#xff0c;GLibc为常见的2.27版本&#xff0c; Allocate申请函数&#xff08;其中有两个输入函数Read_8Int、Read_context&#xff1b; 还存在着后门函数&#xff1b; 关键点在于如何利用…

微服务项目(mybatis与微服务注册)

目录 一、SpringBoot整合MybatisPlus 创建自动生成代码子模块 创建商品服务子模块 二、SpringBoot整合 Freeamarker 三、SpringBoot整合微服务&gateway&nginx 整合微服务之商品服务zmall-product 创建并配置网关gateway服务 安装配置SwitchHosts 安装配置Windows…

基于SpringBoot+Vue的疫苗预约管理系统(Java项目)

【辰兮要努力】&#xff1a;hello你好我是辰兮&#xff0c;很高兴你能来阅读&#xff0c;昵称是希望自己能不断精进&#xff0c;向着优秀程序员前行&#xff01; 博客来源于项目以及编程中遇到的问题总结&#xff0c;偶尔会有读书分享&#xff0c;我会陆续更新Java前端、后台、…

RabbitMQ详解(一):RabbitMQ相关概念

RabbitMQ是目前非常热门的一款消息中间件&#xff0c;不管是互联网大厂还是中小企业都在大量使用。作为一名合格的开发者&#xff0c;有必要对RabbitMQ有所了解&#xff0c;本系列是RabbitMQ快速入门文章&#xff0c;主要内容包括RabbitMQ是什么、RabbitMQ核心概念、五种消息模…

设备管理(7)

设备管理 1 I/O硬件组成 设备的类型&#xff1a; 块设备&#xff1a;如&#xff1a;磁盘、磁带&#xff0c;块大小512B~32KB&#xff0c;通常为512B。块设备的特点是速度高、随机访问、I/O采用DMA。字符设备&#xff1a;如&#xff1a;键盘、行式打印机。特点是速度低、不可寻…

河道治理漂浮物识别监测系统 yolov7

河道治理漂浮物识别监测系统通过yolov7网络模型深度视觉分析技术&#xff0c;河道治理漂浮物识别监测算法模型实时检测着河道水面是否存在漂浮物、水浮莲以及生活垃圾等&#xff0c;识别到河道水面存在水藻垃圾等漂浮物&#xff0c;立即抓拍存档预警。You Only Look Once说的是…

LeetCode 1138. 字母板上的路径

【LetMeFly】1138.字母板上的路径 力扣题目链接&#xff1a;https://leetcode.cn/problems/alphabet-board-path/ 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board ["abcde", "fghij…

66 使用注意力机制的seq2seq【动手学深度学习v2】

66 使用注意力机制的seq2seq【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1v44y1C7Tg/?spm_id_from…top_right_bar_window_history.content.click&vd_source75dce036dc8244310435eaf03de4e330 在机器翻译时&#xff0c;…

指针引用字符串问题(详解)

通过指针引用字符串可以更加方便灵活的使用字符串。 字符串的引用方式有两种&#xff0c;下面简单介绍一下这两种方法。 1.用字符数组来存放一个字符串。 1.1 可以通过数组名和下标来引用字符串中的一个字符。 1.2 还可以通过数组名和格式声明符%s输出整个字符串。 具体实…

【项目精选】百货中心供应链管理系统

点击下载源码 近年来&#xff0c;随着计算机技术的发展&#xff0c;以及信息化时代下企业对效率的需求&#xff0c;计算机技术与通信技术已经被越来越多地应用到各行各业中去。百货中心作为物流产业链中重要的一环&#xff0c;为了应对新兴消费方式的冲击&#xff0c;从供货到销…

第五十二章 BFS进阶(二)——双向广搜

第五十二章 BFS进阶&#xff08;二&#xff09;——双向广搜一、双向广搜1、优越之处2、实现逻辑3、复杂度分析二、例题1、问题2、分析3、代码一、双向广搜 1、优越之处 双向广搜是指我们从终点和起点同时开始搜索&#xff0c;当二者到达同一个中间状态的时候&#xff0c;即相…

Python __all__变量用法

事实上&#xff0c;当我们向文件导入某个模块时&#xff0c;导入的是该模块中那些名称不以下划线&#xff08;单下划线“_”或者双下划线“__”&#xff09;开头的变量、函数和类。因此&#xff0c;如果我们不想模块文件中的某个成员被引入到其它文件中使用&#xff0c;可以在其…

【算法题解】15. 设计最小栈

这是一道 中等难度 的题。 题目来自&#xff1a;leetcode 题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在 常数时间 内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void p…

C语言-重点知识总结-建议收藏(完结)

一图带你梳理C语言重点知识。图片解析&#xff1a;这张图从C语言初阶开始&#xff0c;一直讲解到C语言进阶的知识。在C语言初阶&#xff1a;从初识C语言开始学习&#xff1a;初识C语言带你进入C语言的大门&#xff0c;了解C语言的魅力。然后为你讲解C语言的基本语法&#xff1a…

软件测试只会“点点点”,凭什么让开发看的起你?

众所周知&#xff0c;如今无论是大厂还是中小厂&#xff0c;自动化测试基本是标配了&#xff0c;毕竟像双 11、618 这种活动中庞大繁杂的系统&#xff0c;以及多端发布、多版本、机型发布等需求&#xff0c;但只会“写一些自动化脚本”很难胜任。这一点在招聘要求中就能看出来。…

开源代码的寿命为何只有1年?

说实话&#xff0c;如果古希腊的西西弗斯是一个在2016年编写开源代码的开发者&#xff0c;那他会有宾至如归的感觉。著名的西西弗斯处罚&#xff0c;是神话流传下来的&#xff0c;他被迫推一块巨大的石头上山&#xff0c;当登顶之后&#xff0c;只能眼睁睁看着它滚下去&#xf…