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

一些C++入门基础

关键字

图引自  C++ 关键词 - cppreference.com

 命名空间

命名空间解决了C没办法解决的各类命名冲突问题

C++的标准命名空间:std

命名空间中可以定义变量、函数、类型:

namespace CS {//变量char cs408[] = "DS,OS,JW,JZ";int cs = 408;//函数void Func() {cout << "085400" << endl;}//类class student {public:void F() {cout << "bull and horse" << endl;}private:int a = 6;int b = 66;};
}

且命名空间可以嵌套(不常用):

namespace School {int x = 0;namespace CS {//};};

授权

命名空间未展开时,默认不能访问命名空间

全部展开:

using namespace CS;

部分展开(仅可访问部分已展开的变量、函数、类):

using CS::cs408;

或者加上作用域限定符直接访问:

	CS::student st1;st1.F();

合并

如果定义了多个同名的命名空间,会自动合并:

如果合并后有多个同名变量、函数、类型,会出现重定义。

缺省参数

声明或者定义函数时,为参数指定的缺省值,如没有传参时,使用缺省值:

Date(int year = 1, int month = 1, int day = 1) {};

全缺省:

Date(int year = 1, int month = 1, int day = 1) {};

半缺省(部分缺省):

半缺省参数必须从右往左给出,且不能间隔着给。

所以,调用半缺省参数的函数时,传参必须从左往右给出,同样不能间隔。

Date(int year, int month = 1, int day = 1) {};Date(2025);
Date(int year, int month, int day = 1) {};Date(2025,5);

注:在函数声明和定义分离的情况下,不能为声明和定义同时给出半缺省参数,避免声明和定义中的缺省值不同而无法调用。

函数重载

C++允许同一作用域下存在同名函数,条件是:形参的个数 or 类型 or 顺序不同:

Date(int a);
Date(int a, int b);
Date(int a, char b);
Date(char a, int b);

原理

C/C++ 中,一个程序要运行需经历:预处理、编译、汇编、链接;

(每日回顾:C程序预处理(本文包括宏定义)-CSDN博客)

在汇编阶段,对于一个函数,汇编器会为其分配一个地址,并将该地址与函数名关联起来,记录在符号表中;在链接完成之后,会形成完整的符号表。符号表包含了程序中所有符号的名称、地址和属性等信息。

VS中,C和C++的函数名修饰规则对比

 由上图可见,C语言仅在函数名前加 '_' 以在符号表中查找对应函数地址;而C++的函数名修饰中,还与形参有关,这也印证了前文所说函数重载的条件。

特殊情况

函数重载和缺省参数的函数同时存在可能会出现调用歧义:

//无参数 和 全缺省
void F() {};
void F(int a = 1, int b = 2) {};//一个参数 和 半缺省
void F(int a) {};
void F(int a, int b = 2) {};

引用

引用的底层和C指针一样,只是使用更加方便;一个变量的引用,就是给这个已存在的变量取个别名,这个引用与已存在的变量共用同一块内存空间。

int p = 0;
int& pp = p;    // pp是p的引用pp = 1;    // 修改pp,p也会随之修改

特性

1、必须在定义时就初始化;

2、一个变量可以有多个引用:

int p = 0;
int& pp = p;
int& ppp = p;

3、引用被初始化之后,不能再改变指向;

int p = 0;
int q = 1;
int& pp = p;
pp = q;    // 报错,不能再改变指向

使用场景

引用作为参数

void test(int& a){};
int main(){int b = 1;test(b);return 0;
}

引用作为返回值

int& test(int& a){a++;return a;
};
int main(){int b = 1;int ret = test(b);return 0;
}

 上面这段代码,其实test函数中返回的a变量,在出了函数作用域之后已经销毁,只不过我们用ret立刻接收了该引用的值;实际上返回的引用,已经是被释放的空间

所以,如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

效率

使用传值传参和使用值作为返回值类型时,实际上都是实参或者返回变量的一份临时拷贝;所以当值较大时,效率必然低于使用引用传参或者使用引用作为返回值类型。

和指针对比

引用的底层实现,与指针相同,只不过使用时更为方便。

1、引用 在概念上是一个变量的别名,而指针存储地址;

2、引用在定义时必须初始化指向实体,指针不必;

3、引用在初始化引用一个实体后,不能再改变指向,而指针可以;

4、sizeof(引用) 是引用类型的大小,而指针始终是地址所占字节数大小;

5、引用++ 是引用的实体++,而指针++ 是向后偏移;

6、没有多级引用,有多级指针;

7、访问实体方式不同:引用 编译器会处理,而指针需要显式解引用;

8、引用使用起来更安全。

内联函数

以inline修饰的函数为内联函数。

普通函数在调用时,需要建立栈帧;内联函数会在编译时直接展开,没有建立栈帧的开销,提升程序运行效率。

有点像C中的宏函数,只不过宏是完全的只有替换,而内联函数是展开函数体。

inline void test(int a){};

特性

1、以空间换时间,但如果函数体过大,会使文件变大;

2、不同编译器的实现不同,一般编译器会将函数规模较小(10行左右)、且不是递归、且频繁调用的函数,采用inline修饰,否则会忽略。(内联说明只是向编译器发出的一个请求,编译器可以选择忽略这个请求)

3、inline函数不建议声明和定义分离。因为内联函数展开后,就没有函数地址了,只有声明就会找不到定义,报链接错误。

auto关键字(C++11)

auto作为一 个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。简单来说,auto可以推导当前变量类型。

int a = 0;
auto b = a;
auto c = 'a';

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto 的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

你不能使用auto来推导未知类型。

auto常用来与范围for、lambda表达式搭配使用。

范围for(C++11)

范围for使得在遍历一个有范围的集合时,更加方便:

int arr[10] = {0};
for (auto a : arr){cout << a << endl;
}

这段代码会依次取数组中所有的数据赋值给 a ,打印;

使用条件

1、for 循环迭代的范围是确定的(下图展示了不确定的范围);

void test(int arr[]){for(auto a : arr){cout << a << endl;}
}

2、迭代的对象要实现++和==的操作。

nullptr

int* p1 = NULL;
int* p2 = 0;

在C的头文件 stddef.h 中,有部分代码:

(条件编译见每日回顾:C程序预处理(本文包括宏定义)-CSDN博客)

#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

NULL实际是一个宏,可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。

但是如果有:

void test(int a)
void test(int* a){};
int main(){test(NULL);
}

那么test(NULL) 到底调用谁?这就出现了问题,C++11中通过引入关键字nullptr 用来初始化空指针。

相关文章:

  • 二维码外面套一个黄色圆圈 之间间隙太大
  • 小红书“开门”,摸到电商金钥匙?
  • 设计模式----软考中级软件设计师(自用学习笔记)
  • 【nRF9160 常用prj.conf配置与AT指令介绍】
  • 基于MakeReal3D的虚拟预装系统:飞机装配效率与精度的双重突破
  • QT6 源(113)篇二:阅读与注释工具栏 QToolBar,给出源码
  • C46-二维数组与指针的总结
  • 谁在用AI掘金?——近屿智能教你掌握AI时代的生存密码
  • 开源运维工具HHDESK源码开发
  • 【DCGMI专题2】---DCGMI 常用命令详解与生产实例分析
  • 《微机原理与接口技术》第 8 章 常用接口芯片
  • es学习小结
  • LeetCode-前缀和-和为K的子数组
  • 便捷的Office批量转PDF工具
  • 第32节:基于ImageNet预训练模型的迁移学习与微调
  • 鸿蒙路由参数传递
  • X 下载器 2.1.42 | 国外媒体下载工具 网页视频嗅探下载
  • 分析 redis 的 exists 命令有一个参数和多个参数的区别
  • Python的sys模块:系统交互的关键纽带
  • 【开源工具】文件夹结构映射工具 | PyQt5实现多模式目录复制详解
  • 六个最伤脊柱的姿势,你可能天天在做
  • 围绕“工程智能”系统布局,同济大学官宣成立五大研究院
  • 山西持续高温:阳城地表温度72.9℃破纪录,明日局部地区仍将超40℃
  • 存款利率、LPR同日下调,机构称对银行的影响偏正面
  • 新造古镇丨江浙沪重点打造的“水乡客厅”,古镇也能串着玩?
  • 音著协宣布胜诉,虎牙公司终审被判侵权