C++初学(2)
C++变量类型
变量类型其实不用过多阐述,和数据类型相似,变量仅仅是可操作存储区的名称而已,C++还有其他类型的变量,如枚举、引用、数据结构和类等。
枚举类型:enum,用于定义一组命名的整数常量。
变量声明
声明是向编译器保证变量是按照给定的类型和名称而存在,声明只有在编译时才有意义,声明和定义是不同的概念,声明可以多次,而变量的定义只有一次;多个文件且只有一个文件定义变量,变量的声明就显得非常有用,使用extern关键字在任意一个地方声明一个变量。
extern 的用法:
1 | extern int i; //声明,不是定义 |
左值和右值
这两个概念和C中是一样的,只需要注意右值不能出现在赋值号的左边。
C++变量作用域
定义变量的三个地方:
1.函数和代码块的内部,局部变量
2.函数参数的定义中声明的变量,形式参数
3.函数外部声明的变量,全局变量
作用域一般分为以下几种:
局部作用域:变量只能在函数内部访问,函数调用时创建,执行结束销毁。
全局作用域:变量可以被程序中任何函数访问,程序开始时创建,程序结束销毁。
块作用域:例如循环,只能在代码块中被访问,循环中创建,循环结束而销毁。
类作用域:在类中内部声明的变量,可以被内部所有的成员函数访问,与类生命周期一致。
Tip:若是内部作用域的变量和外部作用域的变量重名,内部变量会将外部变量覆盖。
C++常量
常量是固定值,在程序执行期间不会改变,就像是常规的变量,只是值不能变,常量可以是任何的数据类型。
整数常量:可以是十进制、八进制和十六进制,整数常量也可以带后缀,U表示无符号整数,L表示长整数。
浮点常量:由整数部分、小数点和小数部分或指数部分组成,主要是小数形式和指数形式表示。
布尔常量:属于关键字,只有true 和 false,不应该看作0和1。
字符常量:常常是在单引号中,还有就是一些带反斜杠的转义字符。
字符串常量:通常在双引号””之中,包含字符常量的字符、转义序列和通用字符。
定义常量
C++和C中并没有很大的区别
1.#define预处理器
1 |
|
2.const关键字
1 |
|
Tip:常量定义一般使用大写字母。
C++修饰符类型
修饰符前面已经阐述过了,其实主要的差异就是集中在signed和unsigned两个修饰符。
C++类型限定符
类型限定符提供了变量的额外信息,用于定义时改变默认行为的关键字。
const:只读变量,值不能被修改。
volatile:该变量的值可能会被程序外的因素改变,硬件和其他线程等。
restrict:该关键字修饰的指针是唯一访问它所指向对象的方式。
mutable:该关键字用于修饰类的成员变量,该变量可以被修改,即使对象是const
static:用于定义静态变量,说明只能用于当前文件或者当前函数。
register:定义寄存器变量,说明其需要被频繁使用,存在寄存器中,提高效率。
实例:
1 | const int num = 10; |
在C++中的static除了和C一样的用法之外,在类的定义中还有一些重要的概念,在类中,声明为static的类成员分为两类,静态成员变量,静态成员函数;其中静态成员变量一定要在类外进行初始化。
1.静态成员为所有该类的对象所共有,不属于某个具体的个例
2.静态成员变量要在类外定义,定义时不添加static
3.静态成员函数没有隐藏的this指针,不能访问任何非静态成员
4.访问静态成员变量的特殊方式
5.静态成员和普通的一样,具体三种访问级别,可以具有返回值
static详解:
https://blog.csdn.net/weixin_45031801/article/details/134215425
C++存储类
这个概念其实我并不清楚为什么需要单独拎出来说,因为其实还是这几个关键字,定义了程序中变量和函数的范围和生命周期,存储类说明符一般放在修饰类型的前面,按照现有的资料来说,存储类说明符只是关键字的子集。
存储类:
auto、register、static、extern、mutable、thread_local等
其中最后一个是关键字中没有的,thread_local主要用于具有线程局部存储期的变量,每个线程都有自己的独立副本,线程局部变量和线程的生命周期一致。
auto:声明变量时根据初始化表达式自动推断该变量的类型;声明函数时函数返回值的占位符。
1 |
|
register:同关键字中一样的用法,不再赘述
static:同关键字
extern:同关键字
mutable:同关键字,适用于需要在const环境中修改状态的特定情况,不是普遍的设计模式。
thread_local:用于多线程环境管理线程特有的变量,每个线程彼此独立。
1 |
|
Tip:由于每个线程都有独立的副本,该类型的变量访问速度相较全局和静态稍慢;且存储类型是静态存储持续时间,在程序运行期间会一直存在。
C++函数
主函数main,其余的常规的函数和C一致,定义函数、函数声明、调用函数等。
函数参数
函数需要使用参数,则必须声明接受参数值的变量,这些被称为形参;形参和函数内部的变量一样,进入函数时创建,退出时销毁,调用函数时,有三种向函数传递参数的方式:
传值调用:该方法把参数的实际值赋值给函数的形式参数,基于此修改函数内的参数对实际的参数没有影响。
指针调用:该方法是将参数的地址赋值给形式参数,在函数内修改形式参数会影响到实际参数。
引用调用:该方法是将参数的引用赋值给形式参数,在函数内修改亦会影响实际参数。
参数列表中的参数我们可以指定其默认值,调用时若是留空,则会使用这个默认值。
Lambda函数与表达式
C++11提供了对匿名函数的支持,也称为Lambda表达式,其把函数看作对象,可以将它们赋值给变量和作为参数进行传递,还可以像函数一样对其求值。
表达式具体形式:[capture] (parameters)->return-type{body}
capture:外部捕获的值
parameters:表达式的参数
return-type:返回值的类型
body:表达式的本体
在Lambda表达式中,可以访问当前作用域的变量,这是C++的闭包行为,C++的闭包行为有传值和传引用的区别,可以使用前面的[capture]来指定:
1 | [] // 沒有定义任何变量。使用未定义变量会引发错误。 |
闭包是一种捕获外部作用域变量的函数,结合了函数体和变量,允许函数在离开作用域之后仍然可以访问这些变量,捕获的变量和函数体共同组成了对象(闭包),持有变量的方式:值捕获和引用捕获。
捕获变量的生命周期和闭包对象一致,捕获的值在闭包期间有效。引用捕获的变量需要保证原变量在闭包的生命周期内有效,否则会出现未定义行为。
对于值捕获的变量,使用mutable可以使得它在闭包内部可修改,且不影响外部变量。闭包可以将外部变量封装成持久状态,在多次调用中保持状态。
另外还有一点,对于[=]和[&]的形式,lambda表达式可以直接使用this指针,对于[]的形式,要使用this指针,必须显式传入。
1 | [this]() { this->someFunc(); }(); |
捕获this,才可以使用当前对象的成员变量和成员函数,当然捕获this有一些注意事项,和前面类似,主要是生命周期的问题可能会导致悬空引用,从而引发未定义的行为。其次,若捕获的this是常量指针,那么是无法对对象成员进行修改的,若是需要修改,则需要使用[this]或者[&]来进行捕获。
剩下的部分基本就是C语言中相同的内容。