1.1.1 程序的内存分布
- 代码区
- 全局数据区:静态数据,全局数据不会因为函数的退出而释放空间。
- 堆区:new 产生的动态数据存在堆区
- 栈区:函数内部的自动变量,自动变量一般会随着函数的退出而释放空间
1.1.2 static
c++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static。
静态变量都在全局数据区分配内存,包括静态局部变量。全局数据区的数据不会因为函数的退出而释放空间。
1.1.2.1 面向过程设计中的static
- 静态全局变量:在全局变量前加 static关键字
void fn();
static int n;
int main()
{
n=10;
cout<<n<<endl;
fn();
return 0;
}
void fn()
{
n++;
cout<<"fn "<<n<<endl;
}
1.静态变量在全局数据分配内存
2.未经初始化的静态变量会被自动初始化为0, 自动变量的值是随机的,除非它被显式的初始化
3.静态全局变量在声明它的整个文件都是可见的,但是在文件之外是不可见的。
1.静态全局变量不能被其他文件所用
2.其他文件可以定义相同名字的变量,不会发生冲突
test_1.cpp
#include <iostream>
using namespace std;
void fn();
static int n;
int main()
{
n=10;
cout<<n<<endl;
fn();
}
void fn()
{
n++;
cout<<" test1 : "<<n<<endl;
}
test_2.cpp
#include <iostream>
using namespace std;
void fn();
// 静态全局变量不能被其他文件所用
//2.其他文件可以定义相同名字的变量,不会发生冲突
extern int n;
int main()
{
n=10;
cout<<n<<endl;
fn();
return 0;
}
void fn()
{
n++;
cout<<"fn "<<n<<endl;
}
- 静态局部变量:在局部变量前加static关键字
using namespace std;
void fn();
int main()
{
fn();
fn();
fn();
return 0;
}
void fn()
{
static int n=10;
cout<<n<<endl;
n++;
}
一般函数中定义的变量,在程序运行中会分配栈内存,但随着程序退出函数体,系统就会收回栈内存,局部变量也会失效。但是有时候需要在每次调用的时候对变量进行保存,一般可以通过全局变量来实现。但是定义全局变量的话,变量已经不属于函数本身,不再受函数控制,给程序维护带来不变。
局部静态变量可以实现保存数据,并且属于函数体。
1.变量存储在全局数据区
2.静态局部变量在程序执行到该对象的声明处时首次被初始化,以后的函数调用不再进行初始化
3.静态局部变量一般在声明处初始化,如果没有显示初始化,会被自动初始化为0
4.始终保存在全局数据区,直到程序运行结束,但作用域为局部作用域,当定义它的函数或语句块结束时,作用域随之结束。
- 静态函数:在函数的返回类型前加上static关键字
静态函数只能在声明它的文件中可见,不能被其他文件使用。
#include <iostream>
using namespace std;
static void fn();
int main()
{
fn();
fn();
return 0;
}
void fn()
{
int n=10;
cout<<"fn : "<<n<<endl;
n++;
}
1.静态函数不能被其他文件使用
2.其他文件可以定义相同名字的函数,不会发生冲突
1.1.2.2 面向对象程序设计中的static
- 静态成员变量:在类内成员的声明前加上static关键字
staticParams.h
class staticParams
{
public:
staticParams(int x, int y, int z)
:a(x),b(y),c(z)
{
sum+=a+b+c;
}
void getSum()
{
std::cout<<sum<<std::endl;
}
private:
int a,b,c;
static int sum;
};
staticPrams.cpp
#include "staticsamples.h"
int staticParams::sum = 0;
main.cpp
#include "static/staticsamples.h"
using namespace std;
//static void fn();
int main()
{
fn();
fn();
staticParams M(0,1,2);
M.getSum();
staticParams N(1,2,3);
N.getSum();
M.getSum();
return 0;
}
1.对于非静态数据成员,每个类对象都有自己的copy,但是静态数据成员被当做是类的成员,无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份。
2.静态数据成员是所有对象共享的,可以被任何一个对象更新。
3.静态数据成员存储在全局数据区,静态数据是成员定义时要分配空间,所以不能在类声明中定义。
4.静态数据成员和普通数据成员一样遵从public,private,protected访问规则
5.静态数据在全局数据分配内存,在没有产生对象时,作用域就可见,可以通过以下方式访问,操作
int n =staticParams::sum;
6.静态数据成员初始化方式为:
int staticParams::sum = 0;
7.静态数据成员主要用在各个对象都有的相同的某个属性的时候,这样在使用的时候,只需要修改依此,所有实例的对象就都改变了。
1.静态数据成员没有进入程序的群居名字空间,因此不存在与程序中其他全局名字冲突的可能性
2.可以实现信息隐蔽,静态成员可以是private成员,全局变量不能。
- 静态成员函数
staticSample.h
class staticSamples
{
public:
staticSamples(int x,int y, int z)
{
this->a=x;
this->b=y;
this->c=z;
sum+=a+b+c;
}
static void getSum()
{
//std::cout<<a; ****error****
std::cout<<sum<<std::endl;
}
private:
int a,b,c;
static int sum;
staticSample.cpp
int staticSamples::sum =0;
1.类的全局实现,普通的成员函数隐含了this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。静态成员函数没有this指针。
2.因此,静态成员函数不能访问类对象的非静态数据变量和非静态成员函数。
3.出现在类外的函数定义不能指定关键字static
4.静态修饰内容之间可以互相访问
5.非静态修饰内容可以访问静态修饰内容
6.静态修饰不能访问非静态修饰内容
7.由于没有this指针的额外开销,静态成员与全局成员相比,速度稍快
|