- 浏览: 55132 次
- 性别:
- 来自: 长春
-
最近访客 更多访客>>
文章分类
最新评论
-
select*from爱:
引用
今天看书的时候学了一个函数,分享给大家:
请问lz,你 ...
window.onload函数用法
static关键字是C,C++中都存在的关键字,它主要有三种使用方式
(1)局部静态变量
(2)外部静态变量/函数
(3)静态数据成员/成员函数
下面就这三种使用方式及注意事项分别说明
一、局部静态变量
在C/C++中,局部变量按照存储形式可分为三种auto,static,register。
与auto类型(普通)局部变量相比,static局部变量有三点不同
1.存储空间分配不同
auto类型分配在栈上,属于动态存储类别,占动态存储区空间,函数调用结束后自动释放,而static分配在静态存储区,在程序整个运行期间都不释放。两者之间的作用域相同,但生存期不同。
2.static局部变量在所处模块在初次运行时进行初始化工作,且只操作一次。
3.对于局部静态变量,如果不赋初值,编译期会自动赋初值0或空字符,而auto类型的初值是不确定的。(对于C++中的class对象例外,class的对象实例如果不初始化,则会自动调用默认构造函数,不管是否是static类型)
特点:static局部变量具有“记忆性”与生存期的“全局性”。
所谓“记忆性”是指在两次函数调用时,在第二次调用进入时,能保持第一次调用退出时的值。 (和全局变量比起来,static可以控制变量的可见范围,详见注意事项二)
示例程序一
#include <iostream>
using namespace std;
void staticLocalVar()
{
static int a = 0; //运行期时初始化一次
//下次再调用时,不进行初始化工作
cout<<"a="<<a<<endl;
++a;
}
int main()
{
staticLocalVar(); //第一次调用,输出a=0
staticLocalVar(); //第二次调用记忆了第一次退出时的值,输出a=1
return 0;
}
应用:
利用“记忆性”,记录函数调用的次数 示例程序一:利用生存期的“全局性”,改善”return a pointer / reference to a local object”的问题。Local object的问题在于退出函数,生存期即结束。利用static的作用,延长变量的生存期。
注意事项:
1.“记忆性”,程序运行很重要的一点就是可重复性,而static变量的“记忆性”破坏了这种可重复性,造成不同时刻至运行的结果可能不同。
2.“生存期”全局性和唯一性。普通的local变量的存储空间分配在stack上,因此每次调用函数时,分配的空间都可能不一样,而static具有全局唯一性的特点,每次调用时,都指向同一块内存,这就造成一个很重要的问题——不可重入性!!!
这样在多线程程序设计或递归程序设计中,要特别注意这个问题。
比如:
static int id = 0;
sql = "select * from table where id=" + id;
如果这样写的话,在单机测试的时候没有问题,但是在多人同时对数据进行测试的时候,就会有问题了。假如,A用户访问他的id是20,则id的值在内存中为20,而此时B用户访问,他的id是30,则id在内存中的值是30,A用户的id值则被更改了。如果此时你将这个方法用非静态成员来写,则不会出现这样的情况。因为非静态成员是你声明的时候,实例化的时候才会分配内存。所以A用户访问的时候,App会因为A实例化而给A用户的请求分配内存。而B用户访问的时候也一样会因为B用户的访问而分配内存。所以两个用户访问的是不同的内存块,所以不会出现数据覆盖和错乱的现象。 具体应用如下:
① const char * IpToStr(UINT32 IpAddr)
② {
③ static char strBuff[16]; // static局部变量, 用于返回地址有效
④ const unsigned char *pChIP = (const unsigned char *)&IpAddr;
⑤ sprintf(strBuff,"%u,%u,%u, %u", pChIP[0],pChIP[1],pChIP[2],pChIP[3]);
⑥ return strBuff;
⑦ }
假设现在有两个线程A,B运行期间都需要调用IpToStr()函数,将32位的IP地址转换成点分10进制的字符串形式。现A先获得执行机会,执行IpToStr(),传入的参数是0x0B090A0A,顺序执行完应该返回的指针存储区内容是:”10,10,9,11”,现执行到⑥时,失去执行权,调度到B线程执行,B线程传入的参数是0xA8A8A8C0,执行至⑦,静态存储区的内容是192,168,168,168。当再调度到A执行时,从⑥继续执行,由于strBuff的全局唯一性,内容已经被B线程冲掉,此时返回的将是192,168,168,168字符串,不再是10,10,9,11字符串。
二、外部静态变量/函数
在C中static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。
下面是a.c的内容
char a = 'A'; // global variable
void msg()
{
printf("Hello\n");
}
下面是main.c的内容
int main(void)
{
extern char a; // extern variable must be declared before use
printf("%c ", a);
(void)msg();
return 0;
}
你可能会问:为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。
但为了限制全局变量/函数的作用域,函数或变量前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。注意此时,对于外部(全局)变量,不论是否有static限制,它的存储区域都是在静态存储区,生存期都是全局的。此时的static只是起作用域限制作用,限定作用域在本模块(文件)内部。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
三、静态数据成员/成员函数(C++特有)
C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数。这是与普通成员函数的最大区别,也是其应用所在,比如在对某一个类的对象进行计数时,计数生成多少个类的实例,就可以用到静态数据成员。在这里面,static既不是限定作用域的,也不是扩展生存期的作用,而是指示变量/函数在此类中的唯一性。这也是“属于一个类而不是属于此类的任何特定对象的变量和函数”的含义。因为它是对整个类来说是唯一的,因此不可能属于某一个实例对象的。(针对静态数据成员而言,成员函数不管是否是static,在内存中只有一个副本,普通成员函数调用时,需要传入this指针,static成员函数调用时,没有this指针。)
当然说到static,就避免不了要谈到static变量的初始化,
比如
class A
{
public:
A(int val);
private:
int mVal;
};
class B
{
private:
static A m_A;
};
m_A怎么初始化?
规则:static成员一定要在类外初始化。
这是因为被static声明的类静态数据成员,其实体远在main()函数开始之前就已经在全局数据段中诞生了(见《Inside The C++ Object Model》page247)!其生命期和类对象是异步的,(而且静态语意说明即使没有类实体的存在,其静态数据成员的实体也是存的)这个时候对象的生命期还没有开始,如果你要到类中去初始化类静态数据成员,让静态数据成员的初始化依赖于类的实体,,那怎么满足前述静态语意呢?难道类永远不被实例化,我们就永远不能访问到被初始化的静态数据成员吗?
另外类定义仅仅只是定义而已,没有分配内存空间的,所以不能初始化。 除了使用static const int SIZE = 10; 或 enum{SIZE = 10};参看C++ Primer叙述如下:
【Ordinarily, class static members, like ordinary data members, cannot be initialized in the class body. Instead, static data members are normally initialized when they are defined.
One exception to this rule is that a const static data member of integral type can be initialized within the class body as long as the initializer is a constant expression:
class Account {
public:
static double rate() { return interestRate; }
static void rate(double); // sets a new rate
private:
static const int period = 30; // interest posted every 30 days
double daily_tbl[period]; // ok: period is constant expression
};
A const static data member of integral type initialized with a constant value is a constant expression. As such, it can be used where a constant expression is
required, such as to specify the dimension for the array member daily_tbl.
When a const static data member is initialized in the class body, the data member must still be defined outside the class definition.
When an initializer is provided inside the class, the definition of the member must not specify an initial value:
// definition of static member with no initializer;
// the initial value is specified inside the class definition
const int Account::period;】
哦,还有一点需要补充的是static 成员应该在.cpp文件里定义,而不是放在.h文件中。一般的c++都是把一个.cpp文件编译成一个.obj文件,我们定义的static成员全局唯一,需要找一个obj文件放,你放在头文件里面,可以被include很多次,那到底放在那个obj里面呢?编译器不知道了吧,所以写在一个.cpp文件里面,这样才好办,编译器才知道放在.obj里面,link的时候也好办,明白了吧。
另外,在设计类的多线程操作时,由于POSIX库下的线程函数pthread_create()要求是全局的,普通成员函数无法直接做为线程函数,可以考虑用static成员函数做线程函数。(
发表评论
-
基于 Visual C++6.0 的 DLL 编程实现
2010-09-26 10:29 813一、前言 自从微 ... -
指针高级--<高质量编程>
2010-09-26 10:27 710// execise2.cpp : Defines the ... -
#pragma使用
2010-09-26 09:28 789尽管 C 和 C++ 都 ... -
宏定义与空格
2010-09-26 09:08 1348宏定义与空格 在宏定义中,如果宏有多行,每行的后面必须 ... -
vc编译链接错误--LNK2001,LNK2019,
2010-09-26 08:39 1408-- LINK2001 学习VC++ ... -
高手讲解:探索C++的秘密之详解extern
2010-09-25 17:06 763以下是引用片段: #ifdef __cpl ... -
在VC中链接动态链接库的方法简要说明
2010-09-25 17:03 841方法一:windows提供了一套函数, ... -
MFC中消息循环处理的几个函数之间的区别
2010-09-25 16:45 892Windows编程中一个比较原始的问题就是消息循环,现在很少有 ... -
数据库在C++程序中使用方法
2010-09-25 16:26 593在本教程中,我假设大家都知道如何使用C ... -
RAPI初始化算法和SAMPLE CODE
2010-09-16 11:46 849RAPI全写为Remote Application Inter ... -
SQL Server 2005 连接字符串
2010-09-15 08:56 831SQL Native Client ODBC Driver ... -
VC++连接SQL Server2005 数据库
2010-09-15 08:53 1159以前一直使用sql server 20 ... -
五大内存分区
2010-09-14 14:07 629五大内存分区 在C++中,内存分成5个区,他们分别是堆、栈、自 ...
相关推荐
static关键字详解: 内容摘要: 一、static关键字定义属性 二、static属性与非static属性还有一个最大的区别,所有的非static属性必须产生实例化对象之后...五、static关键字(主方法) 适合新手快速学会static关键字。
"关于static关键字的总结" static 关键字是 Java 语言中一个非常重要的概念,它可以用来修饰变量、方法、内部类和代码块等。下面我们将详细介绍 static 关键字的由来、作用和用法。 一、static 关键字的由来 在 ...
在Java编程语言中,`static`关键字是一个非常重要的修饰符,它有多种用途,涉及到类、对象以及变量和方法的生命周期...通过学习这个视频教程,你将能够深入理解`static`的含义和使用场景,从而更好地进行面向对象编程。
实践最重要,所以我的是理论加实例绝对好理解。。
1. 工具类:可以使用static关键字来创建工具类,例如`Math`类,所有数学操作都可以使用静态方法调用。 2. 单例模式:可以使用static关键字来实现单例模式,例如: ```java public class Singleton { private ...
在课堂中 已经简要介绍了 static 关键字的使用 我们知道 static 关键字可以用来修饰 类的成员变量 成员方法或者是代码块 下面我们就来说说这个 static 关键字 有时候程序员可能需要定义一个类成员 对它的使用不依赖...
"Java 程序显示类中 Static 关键字的用法" Java 中的 static 关键字是 Java 语言中一个非常重要的概念,它主要用于内存管理。静态关键字用于共享给定类的相同变量或方法。用户可以将静态关键字应用于变量、方法、块...
### static关键字详解 在Java编程语言中,`static`关键字是一个非常重要的概念,它用于定义类成员(变量、方法和内部类)的行为属性。当一个类成员被声明为`static`时,它就成为了该类的静态成员,这意味着无论创建...
Java 中 static 关键字用法总结 Java 中的 static 关键字是一个非常重要的概念,它可以用来定义静态方法、静态变量和静态块。在 Java 中,静态方法通常在一个类中定义,它们可以在不创建类对象的情况下被调用。静态...
Java中的`final`和`static`关键字是编程中非常重要的两个修饰符,它们分别用于不同的场景,以确保代码的稳定性和高效性。 首先,`final`关键字主要用于表示不可变性。它可以用来修饰类、方法和变量。对于类,如果一...
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通变量和函数,不涉及类;后者主要说明static在类中的作用。
### static关键字的理解与应用 #### 一、static关键字概述 `static`是Java语言中的一个关键字,主要用于定义静态成员变量(静态属性)和静态方法。...理解并熟练掌握它的使用方法对于提高编程技能至关重要。
在C++编程语言中,static关键字是一个非常重要的概念,它在全局变量、局部变量以及函数的声明...通过理解并正确使用static关键字,程序员可以在C++项目中更好地管理变量的作用域和生命周期,以及组织模块化的代码结构。
Static关键字在Java编程语言中扮演着至关重要的角色,它允许我们创建类级别的变量和方法,这些变量和方法不依赖于类的实例即可访问。在深入理解Static关键字之前,我们需要了解类和对象的概念。类是创建对象的蓝图,...
Static关键字可以修饰什么? 从以下测试可以看出, static 可以修饰: 1. 语句块 2. 成员变量(但是不能修饰局部变量) 3. 方法 4. 接口(内部接口) 5. 类(只能修饰在类中的类, 即静态内部类) 6. ...
java中static关键字用法详解 Java中的static关键字是一个非常重要的概念,它在Java编程中扮演着非常重要的角色。本文将详细介绍Java中static关键字的用法,包括静态变量、静态方法和静态代码块等几个方面。 静态...
### C++ `static` 关键字的原理及用法详解 #### 一、引言 在C++编程语言中,`static`关键字扮演着至关重要的角色。它不仅可以用来控制变量和函数的可见性和生命周期,还能在类的设计中发挥独特的作用。正确地理解...
2. **static关键字的说明**: `static`可以修饰属性、方法、代码块和内部类,但不能修饰构造器。被`static`修饰的成员在类加载时就会被创建,它们的生命周期比任何对象都要长。静态成员可以直接通过类名访问,无需...