C++语言中的static和extern

来源:本站
导读:目前正在解读《C++语言中的static和extern》的相关信息,《C++语言中的static和extern》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《C++语言中的static和extern》的详细说明。
简介:我分两个方面来总结,第一方面主要是相对于面向过程而言,即在这方面不涉及到类,第二方面相对于面向对象而言,主要说明static在类中的作用。

一、在面向过程设计中的static关键字

1、静态全局变量

定义:在全局变量前,加上关键字 static 该变量就被定义成为了一个静态全局变量(即全局静态变量)。全局静态变量使得该变量成为定义该变量的

源文件所独享,也即静态变局变量对组成该程序的其他源文件是无效的。具体例子可见C++程序设计教程P103

特点:

A、该变量在全局数据区分配内存。

B、初始化:如果不显式初始化,那么将被隐式初始化为0。

C、访变量只在本源文件可见,严格的讲应该为定义之处开始到本文件结束。

例(摘于C++程序设计教程---钱能主编P103):

//file1.cpp

#include <iostream.h>

void fn();

extern int n;

void main()

{

n=20;

cout < < n < < endl;

fn();

}

//file2.cpp

#include <iostream.h>

static int n; //定义静态全局变量,初始化为0;

void fn()

{

n++;

cout < < n < < endl;

}

文件分别编译能通过,但连接时file1.cpp 中的变量n找不到定义,产生连接错误。

使一个变量只在源文件中全局使用有时是必要的。

第一, 不必担心另外源文件使用它的名字,该名字在源文件中是唯一的。

第二, 源文件的全局变量不能被其他源文件所用,不能被其他的源文件所修改,保证变量的值是可靠的。

D、文件作用域下声明的const的常量默认为static存储类型。

2、静态局部变量

定义:在局部变量前加上static关键字时,就定义了静态局部变量。

特点:

A、该变量在全局数据区分配内存。

B、初始化:如果不显式初始化,那么将被隐式初始化为0。

C、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。

我的简单理解是这样的:

当static用来修饰局部变量时,它就改变了局部变量的存放位置,将其由原来的栈中存放改为全局静态储存区,但是没有改变变量的作用域,还是局限在局

部的{}里。

当static用来修饰全局变量时,它就改变了全局变量的作用域,使其不能被别的程序extern,限制在了当前文件里,但是没有改变其存放位置,还是在全局

静态储存区。

3、静态函数(注意与类的静态成员函数区别)

函数的定义和声明默认情况下在整个程序中是extern的,有时候可能需要使某个函数只在一个源文件中有效,不能被其他源文件所用,这时在函数前面加上

static.

定义:在函数的返回类型前加上static关键字,函数即被定义成静态函数。

特点:

A、静态函数只能在本源文件中使用(这是与普通函数区别)

例(摘于C++程序设计教程---钱能主编P103):

//file1.cpp

void fn();

void staticFn()

void main()

{

fn();

staticFn();

}

//file2.cpp

#include <iostream.h>

static void staticFn();

void fn();

void fn()

{

staticFn();

cout < < "this is fn() n ";

}

void staticFn()

{

cout < < "this is staticFn() n ";

}

连接时,将产生找不到函数staticFn()定义的错误。

作用:

第一, 它允许其他源文件建立并使用同名的函数,而不相互冲突

第二, 声明为静态的函数不能被其他源文件所调用,因为它的名字不能得到,

B、主意事项

在文件作用域下声明的inline函数默认为static类型。

另其它::

C语言中提供了存储说明符auto,register,extern,static说明的四种存储类别。四存储类别说明符有两种存储期:自动存储期和静态存储期。其中auto

和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块是被建立,它在该程序块活动时存在,退出该程序块时撤销。

关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量只能被定义该变量的函数所识别,但是不同于自动变量的是,

static变量在其函数被调用退出后,仍保留其值。下次函数被调用时,可以访问最近一次被修改后的值。static变量的声明方法如下:

static int si = 1;

由于static的以上特性,可以实现一些特定的功能。下面说明常见的两种用途。

1. 统计函数被调用的次数

声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。这是统计函数被调用次数的最好的办法,因

为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。测试代码如下:

#include <stdio.h>

int fun_1(int);

int main()

{

int i;

for (i = 1; i <= 5; i++)

fun_1(i);

return 0;

}

int fun_1(int x)

{

static count = 0;

count++;

printf( "I have been called %d times.n ", count);

return 2*x;

}

输出结果为:

I have been called 1 times.

I have been called 2 times.

I have been called 3 times.

I have been called 4 times.

I have been called 5 times.

2. 减少局部数组建立和赋值的开销

变量的建立和赋值是需要一定的处理器开销的,特别是数组等含有较多元素的存储类型。在一些含有较多的变量并且被经常调用的函数中,可以将一些数组

声明为static类型,以减少建立或者初始化这些变量的开销。示例代码如下:

#include <stdio.h>

#include <time.h>

#include <string.h>

#define ARRAY_SIZE 10000

#define CALL_TIMES 30000

int fun_1();

int fun_2();

int main()

{

int i;

char string2[10], *string3;

time_t t;

time(&t);

string3 = ctime(&t);

printf( "time 1: %s ", string3);

for (i = 1; i <= CALL_TIMES; i++)

{

fun_1();

}

time(&t);

string3 = ctime(&t);

printf( "time 2: %s ", string3);

for (i = 1; i <= CALL_TIMES; i++)

{

fun_2();

}

time(&t);

string3 = ctime(&t);

printf( "time 3: %s ", string3);

return 0;

}

int fun_1()

{

int a[ARRAY_SIZE], b[ARRAY_SIZE];

int i, t;

for ( i = 0; i < ARRAY_SIZE; i++)

{

a[i] = i;

b[i] = ARRAY_SIZE - i;

}

for ( i = 0; i < ARRAY_SIZE; i++)

{

t = a[i];

a[i] = b[i];

b[i] = t;

}

return 0;

}

int fun_2()

{

static int a[ARRAY_SIZE], b[ARRAY_SIZE];

int i, t;

for ( i = 0; i < ARRAY_SIZE; i++)

{

a[i] = i;

b[i] = ARRAY_SIZE - i;

}

for ( i = 0; i < ARRAY_SIZE; i++)

{

t = a[i];

a[i] = b[i];

b[i] = t;

}

return 0;

}

二、面象对象中的static关键字(主要指类中的static关键字)

1、静态数据成员

特点:

A、内存分配:在程序的全局数据区分配。

B、初始化和定义:

a、静态数据成员定义时要分配空间,所以不能在类声明中定义。

b、为了避免在多个使用该类的源文件中,对其重复定义,所在,不能在类的头文件中定义。

c、静态数据成员因为程序一开始运行就必需存在,所以其初始化的最佳位置在类的内部实现。

C、特点

a、对相于 public,protected,private 关键字的影响它和普通数据成员一样,

b、因为其空间在全局数据区分配,属于所有本类的对象共享,所以,它不属于特定的类对象,在没产生类对象时其作用域就可见,即在没有产生类

的实例时,我们就可以操作它。

D、访问形式

a、 类对象名.静态数据成员名

b、 类类型名:: 静态数据成员名

E、静态数据成员,主要用在类的所有实例都拥有的属性上。比如,对于一个存款类,帐号相对于每个实例都是不同的,但每个实例的利息是相

同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局区的内存,所以

节省存贮空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了,因为它们实际上是共用一个东西。

2、静态成员函数

特点:

A、静态成员函数与类相联系,不与类的对象相联系。

B、静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例。

作用:

主要用于对静态数据成员的操作。

调用形式:

A、类对象名.静态成员函数名()

B、类类型名::静态成员函数名()

提醒:《C++语言中的static和extern》最后刷新时间 2024-03-14 01:01:12,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《C++语言中的static和extern》该内容的真实性请自行鉴别。