C/C++ 中的 static
来源:互联网 发布:小学语文教学软件 编辑:程序博客网 时间:2024/05/20 09:11
一 、函数内部的静态变量
在函数体内定义一个局部变量时,编译器在每次函数调用时,使堆栈的指针向下移动,为这些局部变量分配内存。
定义一个全局变量将不仅仅只受这个函数控制。
在C/C++函数内部定义的 static 对象,将存储在程序的静态数据区(static data area)中。
char * c = "abc" 这样的赋值会得到一个警告:不建议从字符常量到 char * 的转换,最好在前面加上 const
1 #include <iostream> 2 using namespace std; 3 4 char oneChar(const char * charArray = 0){ 5 static const char * s; 6 if(charArray){ 7 s = charArray; 8 return *s; 9 }else{ 10 cout <<"un initialized\n"; 11 } 12 if( * s == '\0'){ 13 return 0; 14 } 15 return *s++; 16 } 17 18 char * a = "abcdefghijklmnopqrstuvwxyz"; 19 20 int main(){ 21 oneChar(a); 22 char c; 23 while((c = oneChar()) != 0) 24 cout << c <<endl; 25 return 0; 26 }
从上例可以看到 static const char * s 在每次函数调用时都保留了值。
可以看出来,在上面的函数中容易产生多线程的问题;在设计包含静态变量的函数时,应该记住多线程的问题。
二、静态对象的析构函数
静态对象的析构函数,在程序从main() 中退出时,或者标准C库的 exit()被调用时才被调用。(注意:使用abor() 来退出程序,静态对象的析构函数并不会调用)
如果一个包含局部静态对象的函数从未被调用,那么这个对象的构造函数也不会被调用。
同普通对象的销毁一样,静态对象的销毁也是按照与初始化相反的顺序进行的。
2 #include <fstream> 3 using namespace std; 4 5 ofstream out("statdest.out"); 6 7 class Obj{ 8 char c; 9 public: 10 Obj(char cc):c(cc){ 11 out<<"Obj::Obj() for "<<c<<endl; 12 } 13 ~Obj(){ 14 out<<"Obj::~Obj() for "<<c<<endl; 15 } 16 }; 17 18 Obj a('a'); 19 20 void f(){ 21 static Obj b('b'); 22 } 23 24 void g(){ 25 static Obj c('c'); 26 } 27 28 int main(){ 29 out <<"inside main()"<<endl; 30 f(); 31 out <<"leaving main()"<<endl; 32 33 return 0; 34 }
注意跟踪文件ofstream 的对象out 也是一个静态对象。
在C++ 中,全局静态对象的构造函数是在main()之前调用的,这样就有了一个在进入main() 之前执行一段代码的方法。
三、变量可见性
所有的全局对象都是隐含为静态存储的。
int a = 100;
则 a 被存储在程序的静态数据区,在进入main() 之前,a 已经初始化了。另外,a 对所有的编译单元都是全局可见的。用可见性术语来说,static(只在翻译单元内可见),extern 则明确声明对所有翻译单元都可见。
所以上面的定义和 extern int a = 0 是一样的
但如果这样定义:
static int a = 0 只是改变了a 的可见性,只在本翻译单元内,有时叫文件静态(file static),但并没有改变存储类型—— 仍然驻留在静态数据区,而不管是static 还是 extern
在局部变量中,就总是内部链接了,extern 的修饰没有意义;使用 static 时只会改变变量的存储类型。
四、定义静态数据成员的存储
因为类的静态数据成员有着单一的存储空间,所有必须在一个单独的地方定义,编译器不会分配存储空间,如果一个静态数据成员被声明但没有定义,则连接器会报告错误。
定义必须出现在类的外部(不允许内联),而且只能定义一次。
(1)这些变量唯一合法的初始化地方就是在定义时
(2)这些变量只能够被定义一次
以上两点来保证变量只被创建者所控制。
静态成员函数:
为类的全体对象服务。 可以用普通的方法调用静态成员函数,用“ .” 或者“->” 把它和一个对象相联系。一个更典型的方法是自我调用。
静态成员函数不能访问一般的数据成员,而只能访问静态的数据成员。原因在于:对象的地址(this)是被隐式传递到调用函数的;但static 函数没有this,因此无法访问一般成员。静态函数在速度上比全局函数有少许增长,不仅没有传递this所需要的额外开销,而且还有使得函数在类内的好处。
Static initialization dependency:
对于作用域为多个翻译单元的静态对象来说,不能保证初始化顺序,这可能会导致一些问题。
- C/C 中的static关键字
- C语言中的static
- C/C++中的static
- c 语言中的static
- C语言中的Static
- C/C++中的Static
- C语言中的static
- C语言中的static
- C中的static、extern、#、##
- C/C++中的static
- c语言中的static
- C中的Static
- C/C++中的static
- c语言中的static
- C中的static函数
- C语言中的static
- C中的static
- C,C++中的static
- C++ main函数:处理命令行选项
- (五)CXF整合Spring发布RESTful风格的Web服务
- Java压缩文件和解压缩文件
- 修改struts中:fielderror.ftl 模板
- 10个免费的jQuery可视化编辑器插件
- C/C++ 中的 static
- UVa 11401 Triangle Counting(数学递推)
- 我的Linux书架
- MFC指针获取
- 解决ubuntu每次重启屏幕亮度都重置为最高亮度问题
- yosemite下配置神器PhpStrom开发调试环境
- 事件监视器
- 安装wamp后出现You don't have permission to access / on this server
- 博弈论基础知识