C++中const与static使用的几个要点
2016-12-28 23:17
387 查看
(1) const使用要点
为什么要使用const?
const是定义常量的,而且const定义的常量是有数据类型的,而宏常量是没有数据类型的,所以编译器可以对const常量进行类型安全检查,而对宏常量只是简单的替换,没有类型安全检查,容易出错。const起到保护的作用,防止修改。
const还有一个关键作用是做函数重载。
节省空间:const定义的常量只是给出了对应的内存地址,而#define定义的常量在内存中有若干拷贝。
提高效率:编译器通常不会为普通的const常量分配存储空间,只是将他们保存在符号表中,即它是一个编译期间的常量,没有存储与读取的操作,效率很高。
指针与const
指针与const搭配的两种形式:const int* p; 表示指向的内容是常量,不可变。
int* const p; 表示这个指针本身是常量,不可变。
const int* const p; 都不可变
const与参数传递
const修饰参数的主要意义是参数在函数内不可以改变,所以对一般类型的形参修饰没有意义。如果形参是指针,const int* p这种修饰是有意义的,表明指针指向的内容是不能修改的,但int* const p是没有意义的。
const经常和引用一起用,表明引用的参数在函数内是不可以改变的,这和普通函数按值传递的效果相同,不同之处在于:按值传递是建立对象的副本,然后传递的,而常引用是直接传递地址,所以效率更高。
const修饰函数返回值,是说函数的返回值是常量,不能修改。
对返回值是指针时,则指向的内容不能被修改,且只能赋给const型指针
如果返回值为某个对象为const或某个对象的引用为const ,则返回值具有const属性,则返回实例只能访问类a中的公有数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
注意一点,以下情况在c++中会被报错为重复定义,而不是重载。
int fun1(int a,int b); const int fun1(int a,int b);
const与类
const修饰成员变量 只能在初始化列表中赋值,只有这一种赋值方法。const修饰成员函数,则该函数是不允许修改类的数据成员的。(注意:准确的来说是不允许改变非静态数据成员,可改变静态数据成员)
常对象只能调用被声明为const的成员函数(构造与析构除外)。
class Screen{ public: char get(int x,int y); char get(int x,int y)const; }; const Screen a; Screen b; a.get(0,0); //调用const成员函数 b.get(0,0); //调用非const成员函数
其实这个就是之前提到的基于const的函数重载。
(2)static使用要点
为什么要用static
隐藏:当同时编译多个文件时,所有未加stati4000
c前缀的全局变量和函数都具有全局可见性。如果加了static,就会对其它源文件隐藏。
静态全局变量不能被其它文件所用(全局变量可以);其它文件中可以定义相同名字的变量,不会发生冲突(自然了,因为static隔离了文件,其它文件使用相同的名字的变量,也跟它没关系了);
静态函数跟静态全局变量的作用类似(静态函数不能被其它文件所用; 其它文件中可以定义相同名字的函数,不会发生冲突;)
静态局部变量:延长变量的生存期。
用于函数体内部修饰变量,这种变量的生存期长于该函数。
先说明下内存分布的情况:对于一个完整的程序,在内存中的分布情况如下:
栈区: 由编译器自动分配释放,像局部变量,函数参数,都是在栈区。会随着作用于退出而释放空间。
堆区:程序员分配并释放的区域,new
全局数据区(静态区):全局变量和静态便令的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束释放。
代码区
而静态变量就是存储在静态区的,它随着第一次函数的调用初始化,仅初始化这一次,第二次调用这个函数时不会再初始化,而是直接跳过,然后该变量不会随着函数调用结束而销毁。
静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0
它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,也就是不能在函数体外面使用它(局部变量在栈区,在函数结束后立即释放内存)
用于类:下面讲
static与类
静态数据成员:对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。
静态数据成员存储在全局数据区
因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它;
类的静态数据成员有两种访问形式:
<类对象名>.<静态数据成员名> 或
<类类型名>::<静态数据成员名>
静态数据成员是静态存储的,所以必须对它进行初始化。(程序员手动初始化,否则编译时一般不会报错,但是在Link时会报错误)
初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆;
初始化时不加该成员的访问权限控制符private,public等;
初始化时使用作用域运算符来标明它所属类;
所以我们得出静态数据成员初始化的格式:
<数据类型><类名>::<静态数据成员名>=<值>
class A{
public:
static int a;
};
int A::a = 3; //初始化
静态成员函数
与静态数据成员一样,静态成员函数为类的全部服务而不是为某一个类的具体对象服务。
普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。但是与普通函数相比,静态成员函数不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。
调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
调用类的静态成员函数。
const static int/static const int
对于static const成员和const static成员而言,只有int类型可以在内部初始化,任何类型都可以在类外初始化,但是不可以在构造函数列表初始化。(static const int a=1;并不分配内存,编译时直接将a换成1,放到常量表中)
总结c++类中特殊成员变量的初始化
#include <iostream> using namespace std; class BClass { public: BClass() : i(1), ci(2), ri(i){} // 对于常量型成员变量和引用型成员变量,必须通过参数化列表的方式进行初始化 //普通成员变量也可以放在函数体里,但是本质其实已不是初始化,而是一种普通的运算操作-->赋值运算,效率也低 private: int i; // 普通成员变量 const int ci; // 常量成员变量 int &ri; // 引用成员变量 static int si; // 静态成员变量 //static int si2 = 100; // error: 只有静态常量成员变量,才可以这样初始化 static const int csi; // 静态常量成员变量 static const int csi2 = 100; // 静态常量成员变量的初始化(Integral type) (1) static const double csd; // 静态常量成员变量(non-Integral type) //static const double csd2 = 99.9; // error: 只有静态常量整型数据成员才可以在类中初始化 }; //注意下面三行:不能再带有static int BClass::si = 0; // 静态成员变量的初始化(Integral type) const int BClass::csi = 1; // 静态常量成员变量的初始化(Integral type) const double BClass::csd = 99.9; // 静态常量成员变量的初始化(non-Integral type) // 在初始化(1)中的csi2时,根据著名大师Stanley B.Lippman的说法下面这行是必须的。 // 但在VC2003中如果有下面一行将会产生错误,而在VC2005中,下面这行则可有可无,这个和编译器有关。 const int BClass::csi2; int main() { BClass b; return 0; }
相关文章推荐
- C/C++中 const,extern,static,volatile的使用
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。(转)
- C++ 关键字的使用(const static explict reinterpret_cast)
- C++中static、const使用方法简介
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- C++中const与static使用
- 【C++基础】类型转换运算符的使用方法(reinterpret_cast、 const_cast、static_cast、dynamic_cast)
- 使用标准C++的类型转换符--static_cast、dynamic_cast、reinterpret_cast、const_cast
- C++中 const,extern,static,volatile的使用
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 从零开始学C++之对象的使用(三):static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterdivt_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。(转)
- C/C++中 const,extern,static,volatile的使用(转帖)
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。