C++成员变量、成员初始化列表
class test
{
private:
int a;//普通成员
const int b;//常量成员
static int c;//静态成员
static const int d;//静态常量成员
int &e;//引用类型成员
int* f;//指针类型成员
//int* &g;const int* h; 等等
};
成员变量的初始化有且仅有两种:1、“=”赋值。2、成员初始化列表。其中只能用方法2的有常量成员(不包括静态的)、引用类型成员。
静态成员和静态常量成员由于是类共有的,不是属于某一个对象,因此不能在构造函数中初始化。
静态成员(这里不包括静态常量成员)必须在类外初始化。
成员变量的初始化顺序只与声明的顺序一致,与成员初始化列表顺序无关。
class test
{
//int a=1;//错误:对象没有构造,尚未分配内存空间
int a;
const int b;
//static int c=1;//错误:不可以在声明时初始化
static int c;
const static int d=1;//唯有该类型可以这样
int &e;//引用类型必须用成员初始化列表
public:
test(int _e):b(1),e(_e)/*引用初始化必须为左值*/{}
};
int test::c=1;
const int test::d=1;//也可以这样初始化
变量修饰关键字-restrict
restrict只用于限定指针。用于告知编译器,所有修改该指针所指向内容的操作全部都是基于该指针的,即不存在其它进行修改操作的途径。这样可以帮助编译器进行更好的代码优化,生成更有效率的汇编代码。
const
一、const变量
对于内置算术类型变量,声明为const之后是不允许改变变量的值的。也因为这样,const变量在声明的时候必须进行初始化。
const int i=0;
i=2;//非法!不允许改变
const int a;//错误,要进行初始化
二、const引用
引用初始化绑定给一个变量之后绑定是无法改变的,所以对引用的const主要在于能否用引用来改变绑定变量的值。
1、用const引用绑定一个const变量值的时候,原值无法改变,也不能通过引用改变变量的值
const int i=3;
const int &r=i;
i=2;//错误
r=2;//错误
2、用const引用绑定一个非const变量值的时候,原值可以改变,但是不能通过引用改变。
int i=3;
const int &r=i;
i=2;//正确
r=2;//错误
3、不能用非const引用绑定一个const变量。
const int i=3;
int &r=i;//错误
4、当引用为const时,可以把“它能够转换成自己类型的值”给引用
double pi=3.14;
const int &r=p;//正确,并且r=3
const int &r2=3;//正确,r2=3
这里需要说明的是r并没有引用pi,相反在进行这个操作的时候,分配了专门的内存来存放r所引用的位置,并且值为3,类型为整形。r值到达这块内存的唯一接口。
三、const指针
int i=3;
const int *p1=&i;//不可以通过指针改变i
int *const p2=&i;//不可以改变指针的指向
const int *const p3=&i;//既不可以改变i,也不可以改变指向
四、top-level const和low-levelconst
C++中把直接对变量内存单元中的const限制称为top-level const,即无法改变内存中的值。把对间接指向和引用的值的const限制称为low-level const,即无法改变所指向和所引用的值。在两个变量进行赋值操作时,必须要有同样的level才可以。
1、top-level可以忽略掉
int i=0;//non-level
int *const p=&i;//top-level
2、low-level不可以忽略
const int *p1=&i;
int *p2=p1;//错误 因为p1是low-level而p2不是,所以不能进行p2=p1的操作。
3、在右边的non-leve可以转换为左边的low-level。 而反过来不可以
int i =0;
int *p1=&i;
const int *p2=p1;//ok
p1=p2;//wrong因为p2具有low-level而p1没有,所以可以p2=p1而不能p1=p2。
static
一、面相过程(C)设计中的static
1、静态全局变量
- 在全局变量前,加上关键字static。
- 该变量在全局数据区分配内存(详情参考)。
- 未经初始化的静态全局变量会被程序自动初始化为0。
- 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的(其它文件中可以定义相同名字静态变量,不会发生冲突)。
2、静态局部变量
- 每当程序运行到该语句时都会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。
- 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
- 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
- 它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;
3、静态函数
- 声明函数的文件当中可见,不能被其它文件使用。
二、面相对象(C++)的static关键字
1、静态数据成员
- 该数据成员就是类内的静态数据成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。
- 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。
- 遵从public,protected,private访问规则。
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性。
- 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能。
2、静态成员函数
- 静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分,而不是对象。
- 普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长。
- 出现在类体外的函数定义不能指定关键字static;
typename
1、用在模板定义里,标明其后的模板参数是类型参数
template<typename T, typenameY>
2、模板中标明“内嵌依赖类型名”
typenameiterator_traits<_InputIter>::difference_type __n = 0; //变量定义,说明difference_type是类型而不是一个类静态变量。