C++关键字

static

C:
(1)生命周期:static修饰的变量,存储在内存的静态存储区,无论是在函数内还是函数外,生命周期都是整个程序运行期间,static修饰的函数其生命周期也是整个程序的运行期间
(2)作用域:static修饰的局部变量的作用域就是定义该变量的那个作用域内,static修饰的全局变量的作用域是从这个变量定义开始到整个程序结束
(3)static修饰的变量都存储在静态区
(4)static修饰的变量只能作用于本文件内,即使被extern修饰也不行
(5)static修饰的变量默认初始化为0

C++:
静态成员变量
(1)静态成员变量一定要在类外进行初始化
(2)静态成员变量属于这个类,不属于某个对象,为所有的类对象所共享
(3)静态成员变量必须在类中声明,类外定义,定义时不用加static关键字
(4)包含静态成员变量的类对象的大小并不包含静态成员变量的大小
(5)静态成员变量继承给子类也只存在一份,基类和派生类共享该成员
(6)类内部可以定义静态的类对象成员,即可以定义static修饰的类对象
public:static base A; (正确) public:base A; (错误)
静态成员函数
(1)静态成员函数没有this指针
(2)静态成员函数必须在类中声明,类外定义,定义时不用加static关键字
(3)静态成员函数为所有类对象所共享
(4)静态成员函数没有this指针,只能访问静态成员,普通成员函数可以访问静态和非静态成员

const

const和#define的区别:
(1)const 定义的是一个具有常属性的变量,#define定义的只是一个常数没有类型
(2)#define定义的常量是在预编译阶段进行替换的,而const定义的具有常属性的变量是在编译期间处理确定其值的。
(3)const定义的只读变量从汇编角度来看只是给出了对应的内存地址,而不是像#define一样给出的是立即数
(4)const定义的只读变量在程序运行期间只有一份拷贝(因为它是全局的只读变量,存放在静态区),而define定义的宏常量在内存中有若干个拷贝
(5)const不能重定义,#define可以通过#undef取消某个符号的定义再次进行重新定义
(6)#define可以用来防止头文件的重复引用,const不能

const修饰指针:

1. const int p; // p is a int const. p是一个int型常量 这个很简单
2. const int *p; //p is a point to int const. p是一个指针,指向int型常量
3. int const *p; //同2
4. int * const p; // p is a const point to int. p是一个指向int的const指针
5. const int * const p; //p is a const point to int const. p是一个指向int型常量的const指针
6. int const * const p; //同5

C:
(1)用const定义的常量其实是值不能修改的变量,因此会给它分配内存空间

C++:
(1)const修饰的基本数据类型的常量,编译器会把它放到符号表中不分配存储空间,使它成为一个编译期间的值,没有了内存的读写操作,提高了效率 。const修饰的对象则需要分配存储空间,另外对const使用了extern或者&操作符,也会为const常量另外分配空间。
(2)const修饰形参,一般和引用同时使用,传递效率高,避免对象被修改
(3)const修饰返回值,返回值不可修改
(4)const修饰类数据成员,必须在构造函数的初始化列表中初始化
(5)const成员函数中只能对类中加了mutable关键字的数据成员进行修改
(6)const成员函数修饰的是this指针所指向的对象,保证调用这个函数的对象不会被改变,即表示在类成员函数中不可对类的任何成员进行修改
(7)const成员函数只可以调用const函数,因为在非const成员函数中有可能会改变对象
(8)非const成员函数可以调用const成员函数和非const成员函数
(9)const对象只能调用const成员函数

volatile

volatile关键字意思为易变的,主要用于多线程中,因为有时候某个变量容易被改变,所以我们需要读取当前该变量最新的数据,不需要编译器做优化处理。
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量内存地址中读取数据。如果没有volatile关键字,则编译器可能会优化读取和存储,直接使用寄存器中的值,如果该变量由别的程序更新了的话,将出现读取数据不一致的现象。volatile适用于多线程应用中被几个任务共享的变量。

register

register关键字所修饰的变量叫做寄存器变量,register请求编译器尽可能的将变量存在CPU内部的寄存器而不是用过寻址访问以提高效率,是尽可能的,并不是绝对的,因为CPU的寄存器也就那么点,并不是把所有寄存器变量都放在寄存器中。因为register 变量可能不存放在内存中,所以不嫩用&运算符来获取寄存器变量的地址。
寄存器是CPU不和内存直接打交道,而是通过寄存器,因为寄存器就是一小块一小块的存储空间,它存取的速度要比内存快的多。

explicit

explicit关键字只能用于修饰只有一个参数的构造函数, 它的作用是防止单参数的构造函数隐式类型转换,把一个常量转换成一个对象进行赋值。构造函数默认情况下即声明为implicit(隐式),可以把一个常量赋给一个对象。

sizeof

(1)sizeof是运算符,可用类型、函数、类做参数,而strlen是函数,只能以char*(字符串)做参数,而且要想得到的结果正确必须包含 ‘\0’(通过strlen的实现得知)
(2)数组做sizeof的参数不退化,传递给strlen就退化为指针了
(3)sizeof在程序编译时计算(是类型或者变量的长度),而strlen的结果是要在调用的时候才能计算出来,是用来计算字符串的长度,而不是内存的大小
(4)sizeof返回的是实际空间的大小,并不能计算动态分配的空间
(5)sizeof计算结构体时要考虑内存对齐问题。

struct

结构体是一种复合数据类型,通常编译器会自动的进行其成员变量的对齐,已提高数据存取的效率。
查看某个成员相对于结构体起始位置的偏移量:size_t offsetof( structName, memberName )
默认对齐方式:
约束条件:
(1)结构体第一个成员的地址和结构体的首地址相同
(2)结构体每个成员地址相对于结构体首地址的偏移量是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节
(3)结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加填充字节

struct s{
	char a;
	int b;
	double c;
	char d;
};
sizeof(s) = 1 + (3) + 4 + 8 + 1 + (7) = 24

指定对齐方式:
使用#pragma pack(N)来指定结构体成员的对齐方式,N为2的整数幂
约束条件:
(1)结构体第一个成员的地址和结构体的首地址相同
(2)结构体每个成员的地址偏移需要满足:若N大于等于该成员的大小,则该成员的地址偏移只需满足默认对齐方式即可(地址偏移是其成员大小的整数倍);若N小于该成员的大小,则该成员的地址偏移需为N的整数倍。
(3)结构体总的大小需为N的整数倍,如果不满足则在结构体的末尾进行填充。
(4)如果N大于结构体成员中最大成员的大小,则N不起作用,仍然按照默认方式对齐。

struct s{
	char a;
	int b;
	double c;
	char d;
};
sizeof(s) = 1 + (3) + 4 + 8 + 1 + (3) = 20

位域:
可以更好的利用内存空间,需要区分大小端,口诀“小端小小- 低位字节在内存的低地址端”

struct{
	char a:1; //低地址
	char b:1;
	char c:2; //高地址
}s

union

共用体,也叫联合体,在一个“联合”内可以定义多种不同数据类型的成员,这些成员共享同一段内存,以达到节省空间的目的。union变量所占用的内存长度等于最长的成员的内存长度。

extern

当出现extern “C”时,表示 extern “C”之后的代码按照C语言的规则去编译;当extern修饰变量或函数时,表示其具有外部链接属性,即其既可以在本模块中使用也可以在其他模块中使用。

friend

友元。使其不受访问权限控制的限制。如在1个类中,私有变量外部是不能直接访问的。可是假如另一个类或函数要访问本类的私有变量时,可以把这个函数或类声明为本类的友元函数或友元类。这样他们就可以直接访问本类的私有变量

inline

内联函数,在编译时将所调用的函数代码直接嵌入到主调函数中。各个编译器的实现方式可能不同。

operator

和操作符连用,指定一个重载了的操作符函数,比如,operator+。

public、protected、private

这三个都为权限修饰符。
public:都可访问;
protected:只能在本类、友元、派生类中访问;
private:只能在本类、友元中访问。

子类继承:

继承方式publicprotectedprivate
public继承publicprotected不可用
protected继承protectedprotected不可用
private继承privateprivate不可用

new/delete,malloc/free

(1)new/delete为C++的操作运算符,malloc/free为C的标准库函数
(2)new/delete底层是基于malloc/free来实现的
(3)new会检查数据类型,是类型安全的,malloc无数据类型检查,默认返回值为void*,可通过强制类型转换改变返回值的数据类型
(4)new申请内存空间必须指明要存放的数据类型和要存放对象的数目,malloc只需要指明申请空间的大小
(5)delete和free被调用后,内存不会立即回收,指针也不会指向空,为避免出现野指针,应该将该指针指向NULL。
(6)new/delete动态管理对象,new[]/delete[]动态管理对象数组
(7)new/delete为对象申请释放内存会调用相应的构造函数和析构函数,malloc/free则不会,new[]/delete[]会用4个字节来存放对象个数,确保析构次数准确。所以三者必须配套使用,否则会造成内存泄漏崩溃。

//new/delete举例,由编译器自动计算分配
int*p1 = new int[4];	//动态分配四个字节的空间
int*p2 = new int(4);	//动态分配四个自己的空间,并初始化为4
int*p2 = new int[4];	//动态分配16个字节
delete p1;
delete p2;
delete [] p3;

//malloc/free举例,需手动计算分配
int*p4 = (int*)malloc(sizeof(int)*4);
free(p4);

static_cast、reinterpret_cast、const_cast、dynamic_cast

C++强制类型转换。
static_cast:用于静态转换,任何转换都可以用它,但他不能用于两个不相关的类型转换。
reinterpret_cast:必须用于指针和引用,将一种类型转换为另一种不同的类型;
const_cast:删除const变量的属性,方便赋值;
dynamic_cast:必须用于类的指针或引用,用于将一个父类对象的指针转换为子类对象的指针或引用,基类必须有虚函数,运行时才处理;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值