C++中的几个关键字(static、const、#define、inline、sizeof与strlen、指针与引用、new与malloc)

来源:互联网 发布:java前后端分离 vue 编辑:程序博客网 时间:2024/06/06 21:16

1、C++中static关键字的作用:(推荐博文:http://blog.csdn.net/hackbuteer1/article/details/7487694)

(1)应用于普通变量和函数,不涉及类(静态全局变量、静态局部变量、静态函数)

静态全局变量:在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。

特点包括:

a.该变量存储在全局数据区;

b.未经初始化的静态全局变量会被程序自动初始化为0;

c.静态全局变量在定义它的文件可见,在其他文件不可见(隐藏作用),这样其它文件中可以定义相同名字的变量,不会发生冲突;

静态局部变量:在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。但有时候我们需要在两次调用之间对变量的值进行保存。通常的想法是定义一个全局变量来实现。但这样一来,变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。静态局部变量正好可以解决这个问题。静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。
静态局部变量有以下特点:
    a.该变量在全局数据区分配内存;
    b.静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
    c.静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
    d.它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;

静态函数:在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用,其它文件中可以定义相同名字的函数,不会发生冲突。

(2)类中的static关键字(静态数据成员、静态成员函数)

静态数据成员:在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。

静态数据成员有以下特点:

  • a.对于非静态数据成员,每个类对象都有自己的拷贝。而对于静态数据成员,无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类的所有对象共享访问。所以静态数据成员的值对每个对象都是一样的;
  • b.静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。语句int Myclass::Sum=0;是定义静态数据成员;
  • c.静态数据成员和普通数据成员一样遵从public,protected,private访问规则;
  • d.因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它;

静态成员函数:它为类的全部服务而不是为某一个类对象服务,属于类的内部实现。普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类对象的,通常情况下,this是缺省的。但静态成员函数由于不是与任何对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。

静态成员函数特点:

  • a.出现在类体外的函数定义不能指定关键字static;
  • b.静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
  • c.非静态成员函数可以任意地访问静态成员函数和静态数据成员;
  • d.静态成员函数不能访问非静态成员函数和非静态数据成员;
  • e.由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
  • 注意:不能将静态成员函数定义为虚函数。
2、const关键字的作用

(1)修饰普通变量:

   a.表明该变量是常量,具有不可变性,拥有数据类型,要进行类型检查;

   b.可以节省空间,避免不必要的内存分配。const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

   c.提高了效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

(2)修饰指针

const int* ptr; 
int const* ptr; 
int* const ptr;
如果const位于星号左侧,则const是用来修饰指针所指向的变量,即指针指向常量,不能修改;如果const位于星号右侧,则const就是修饰指针本身,即指针本身就是常量。

(3)修饰成员函数:一些成员函数修改对象,一些不修改,为了使成员函数的意义更加清楚,在不修改对象的成员函数的函数原型后加上const关键字,表示该成员函数不会修改成员变量。如果const放在函数声明前,意味着函数的返回值是常量,意义就完全不同了。注意:在const成员函数中,用mutable修饰成员函数变量名后,就可以修改类的成员变量

3、const define inline的区别

本质:define只是字符串替换,const参与编译运行,inline由编译器控制。

(1)define:仅仅是宏替换,没有数据类型,不做类型检查;不占用内存 

(2)const:拥有类型,做类型检查;占用内存;(const内存效率更高,编译器通常将const变量保存在符号表中,使它成为一个编译期间的常量,没有存储和读取的操作) 
(3)inline:

a.内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用,在编译的时候内联函数可以直接被嵌入到目标代码中;

b.内联函数要做类型检查;

c.inline一般用于如下情况:一个函数不断被调用,而这个函数只有简单几行,函数内不包括for、while、switch等语句,这样对于短小的代码来说,inline增加空间消耗换来了效率提高

4、sizeof关键字

(1)数据对齐:数据所在的内存地址必须是数据长度的整数倍,详细:

a.当结构体内的元素的长度都小于处理器的位数,便以结构体里面最长的数据元素为对齐单位;

b.当结构体内的元素的长度存在大于处理器位数的,便以处理器位数为对齐单位;

c.结构体内类型相同的数据元素与数组一样,存放在连续的地址空间内

(2)sizeof关键字的使用场景:

a.用它看看某种类型的对象在内存中所占的单元字节,这样在动态分配一对象时,可以让系统知道要分多少内存;

b.便于类型的扩充,例如Windows里面就有这个字节大小

c.由于操作数的字节在实现时可能会出现变化,建议在涉及操作数字节大小时用sizeof代替常量计算

d.与存储分配和I/O系统那样的例程进行通信,如malloc,fread

(3)注意:

a.因为静态变量时存储在全局数据区的,而sizeof计算的是栈中分配的内存大小,因此是不会计算静态变量的

b.空类所占空间为1,单一继承的空类所占空间也为1,多重继承的空类空间还是1,虚继承设计虚表(虚指针),指针大小

5、sizeof关键字与strlen的区别

(1)sizeof是运算符,strlen是函数;

(2)sizeof可以用类型做参数,strlen只能用char*指针做阐述,且指针指向的字符串必须是以“\0”结尾的

(3)数组做sizeof的参数是不退化的,而做strlen的参数就退化为指针;

(4)大部分编译程序在编译的时候就把sizeof计算过了,是某一类型或变量的长度,但strlen的结果是在运行的时候才计算的(实质就是循环计算字符串长度)

6、指针与引用的区别:

本质:都是地址的概念,只是指针是一个实体,引用是别名,具体来说:
(1)指针可以为空,引用不能为空;
(2)在参数传递时,指针不会做类型检查,而引用会;
(3)指针会分配内存,而引用不会;
(4)指针可以在运行时改变其所指向的值,引用一旦和某个对象绑定就不再改变 
一般如下情况使用指针:a.考虑到存在不指向任何对象的可能;b.需要能够在不同时刻指向不同的对象


7、new与malloc的区别:
(1)new是运算符,malloc是一个库函数;
(2)new会调用构造函数,malloc不会;
(3)new返回指定类型指针,malloc返回void*指针;
(4)new会自动计算需分配的空间,malloc不行;
(5)new可以被重载,malloc不能。

关于更多指针的内容,后续补上(常量指针,函数指针,指针数组与数组指针,this指针,指向指针的指针,迷途指针,智能指针)

阅读全文
0 0