static in C/C++
最近经常碰到static,之前也使用过,但都是一知半解,所以下决心做个整理总结,搞搞灵清它到底用哪些作用。
一.static in C
1.默认初始化为0:
如果不显式地对静态变量进行初始化,它们将被初始化为0。
static变量存放在Global/Static(全局区/静态区)。在静态数据区,内存中所有的字节默认值都是0x00,所以在程序一开始时static声明的变量会被默认初始化为0。
2.static声明的变量会一直保持其值(局部静态对象)
static变量存放在Global/Static(全局区/静态区)。程序一开始,对其进行唯一一次初始化。被函数调用后,static变量不会消失,计算机会一直记录其值,其生命周期是贯穿函数调用及之后的时间。
#include <stdio.h>
void funcion(); int main()
{
for(int count = ; count <= ; count++) {
printf("第%d次调用:",count);
funcion();
} //for循环中的count内存被释放
return ;
} void funcion()
{
int temp = ;
static int count = ;//只在函数第一次调用时执行,后续函数调用此变量的初始值为上次调用后的值,每次调用后存储空间不释放
printf("temp = %d static count = %d\n",temp--, count--);
}
Eg Code
static count每次调用,其值减1,而temp每次都重新开始都为10。而主函数for循环中的count是在栈区的,作用域只在主函数的for循环中,当循环结束是存储空间自动释放。
3.具有内部链接的静态变量(static variable with internal linkage)
普通的外部变量可以被程序的任一文件所包含的函数使用,而具有内部链接的静态变量只可以被与它在同一个文件中的函数使用。
//举个例子
文件1:a.c
int money = ;
static wife = ;
int main()
{
money++;
printf("wife = %d\n",wife);
}
void function()
{
money--;
printf("wife = %d\n",wife);
}
文件2:b.c
int main()
{
extern int money;
money--;
printf("money = %d\n",money);
return ;
}
a.c中main函数,function函数皆可调用money和wife。b.c用外部声明extern money,是可以输出money = 9的。但是不能extern int wife,因为在a.c 中wife 加了static,其只允许在a.c中使用。(就像好兄弟money是可以共享的,但是wife不行!)
在多文件构成的程序中,如需共享一个外部变量,除了一个声明(定义声明)外,其他所有声明都要加extern;而如果不想被共享的变量,那就在声明时用static,表明该变量具有内部链接。
二.static in C++
1.静态数据成员
#include <iostream>
#include <string>
using namespace std; class Account
{
public:
static int sumAccount; //声明静态数据成员
void calculate() {
amount += amount * interestRate;
}
static double rate() {
return interestRate;
}
static double rate2(double interestRate2 = interestRate) {//使用静态成员作为默认实参。
return interestRate2;
}
// [Error] invalid use of non-static data member 'Account::amount'普通数据成员值不能作为默认实参
// static double showAmount(double Amount = amount) {
// return Amount;
// }
static void rate(double);
private:
string owner;
double amount;
static double interestRate; //声明静态数据成员
static double initRate();
};
double Account::interestRate = 0.30;//定义并初始化静态数据成员
int Account::sumAccount = ; //定义并初始化静态数据成员 int main()
{
Account ac1;
Account *ac2 = &ac1;
Account &ac3 = ac1;
cout << ac1.sumAccount << endl;
cout << ac2->sumAccount << endl;
cout << ac3.sumAccount << endl;
cout << Account::sumAccount << endl;
return ;
}
Eg Account Code
1.静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。静态数据成员只分配一次内存,即只存在一个static成员对象,被该类所有的对象共享。
Eg:每个Account对象都包含数据成员owner和amount。只存在一个interestRate对象被所有Account对象共享。
2.静态数据成员存放在Global/Static(全局区/静态区)。不是由类的构造函数初始化的。必须在类的外部定义和初始化每个静态数据成员,且只能定义一次。一旦被定义,就将存在于程序的整个生命周期。在外部定义静态数据成员时,不能重复static关键字。
Eg:静态数据成员的定义 double Account::interestRate = 0.30;
3.静态数据成员遵守public/protected/private访问规则。
4.静态数据成员的访问: (静态数据成员为public)
①作用域运算符直接访问静态数据成员
Eg: <类类型名>::<静态数据成员名>
Account::sumAccount;
②仍可以用类的对象,引用或者指针来访问静态数据成员。
Eg: <类对象名>.<静态数据成员名>
ac1.sumAccount;
5. 静态数据成员与普通成员区别:
①静态数据成员可以是不完全类型。指针成员可以是不完全类型。数据成员必须是完全类型。
②可以使用静态成员作为默认实参。普通数据成员值本身属于对象的一部分。(Eg:代码中被注释段)
③由于被该类所有的对象共享,改变其值,对于所有对象都改变了,无需逐一改变。
6. 静态数据成员与全局变量的区别:
①静态数据成员在类内,作用域与全局变量不同。且实现了封装性。
②静态数据成员可以实现信息隐藏,可以是private。而全局变量不能。
2.静态成员函数
#include <iostream>
#include <string>
using namespace std; class Account
{
public:
void calculate() {
amount += amount * interestRate;//非静态成员函数可以访问静态数据成员
}
static double rate() {
return interestRate; //静态成员之间可以相互访问
}
static void rate(double);
private:
string owner;
double amount;
static double interestRate;
static double initRate();
};
double Account::interestRate = 0.30; void Account::rate(double newRate) { //定义静态成员函数,不能重复static关键字
interestRate = newRate;
} int main()
{
Account ac1;
Account *ac2 = &ac1;
Account &ac3 = ac1;
cout << ac1.rate() << endl;
cout << ac2->rate() << endl;
cout << ac3.rate() << endl;
Account::rate(0.35);
cout << Account::rate() << endl;
return ;
}
Eg2 Account Code
1.静态成员函数不与任何对象绑定在一起,被所有Account对象共享。它们不包含this指针。静态成员函数不能声明称const的,且不能再static函数体内使用this指针。
2.静态成员函数,既可以定义在类内,也可以定义在类外部。(通常情况,类的静态成员应该在类的外部初始化。)在外部定义静态成员时,不能重复static关键字,只能出现在类的内部声明。
Eg:Eg2 Account Code 行23-25
3.静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数
4.成员函数不用通过作用域运算符就直接使用静态函数。
5.静态成员函数的访问: (静态成员函数为public)
①作用域运算符直接访问静态成员函数
Eg: <类类型名>::<静态成员函数名>
Account::rate();
Account::rate(0.35);
②仍可以用类的对象,引用或者指针来访问静态成员函数。
Eg: <类对象名>.<静态成员函数名>
ac1.rate();
static in C/C++的更多相关文章
- static,你还敢用吗?(二)
为了压系统,昨天小组在测试环境模拟了一大批订单数据.今天上午查看记录的账单计息日志,发现了一大堆的MySqlException MySql.Data.MySqlClient.MySqlExceptio ...
- const,static,extern 简介
const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...
- const extern static 终极指南
const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...
- PHP static静态属性和静态方法
这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么样调用),需要弄明白了他们在内存中存放位置,这样就非常容易理解了.静态属性.方法(包括静态与非静态)在内 ...
- static,你还敢用吗?
我用火狐的HttpRequester测试开发组里一个同学发布的Web API接口,遇到了一个奇怪的问题. 我测试边界情况时,第一次调用响应的结果是正常的,但当再次及以后的请求时,却返回了异常“Syst ...
- Java关键字:static
通常,当创建类时,就是在描述那个类的外观和行为.只有用new创建类的对象时,才分配数据存储空间,方法才能被调用.但往往我们会有下面两种需求: 1.我想要这样一个存储空间:不管创建多少对象,无论是不创建 ...
- Android 中关于static的使用问题
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5251564.html 项目中,在不停地接收串口数据很长一段时间(几小时)后,会偶然性的报错.初步排除了oom ...
- iOS: 在UIViewController 中添加Static UITableView
如果你直接在 UIViewController 中加入一个 UITableView 并将其 Content 属性设置为 Static Cells,此时 Xcode 会报错: Static table ...
- 浅谈Static关键字
1.使用static关键字声明的属性为全局属性 未使用static关键字指定city之前,如果需要将Tom,Jack,Mary三人的城市均改成Beijing,需要再次声明三次对象的city为Beiji ...
- 今天思考一个问题,PHP const和static的区别
static关键字在类中是,描述一个成员是静态的,static能够限制外部的访问,因为static后的成员是属于类的,是不属于任何对象实例,其他类是无法访问的,只对类的实例共享,能一定程序对该成员尽心 ...
随机推荐
- apk重新签名
re-sign.jar中后自动去除签名这个方法,经试验不可用! 1.去除准备重新签名SinaVoice.apk软件本身的签名 将apk文件后缀改为.zip,然后从winrar中删除META-INF文件 ...
- 关于NopCommerce3.6版的@Html.Widget(“home_page_top”)的说明
以首页幻灯片为例子,首页幻灯片是在插件Nop.Plugin.Widgets.NivoSlider里面实现的 首页视图位置 这里其实是加载插件里面的视图内容,具体实现在插件实现 这个是扩展方法,就是执行 ...
- DB2 Magazine 中文版: 访问 iSeries 数据
当您第一次开始学习 DB2 for iSeries 时,一下子要弄清楚如何访问所有数据可能有些令人生畏.我将介绍访问 DB2 for iSeries 数据的一些常见的方法,并展示如何开始开发访问存储在 ...
- Custom Date tag
Custom Date tag: custom date based on pattern format. Default date is current day. <CUSTOMDATE[+, ...
- 过河-状压DP
http://www.luogu.org/problem/show?pid=1052 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上 ...
- 如何利用百度地图JSAPI画带箭头的线?
百度地图JSAPI提供两种绘制多折线的方式,一种是已知多折线经纬度坐标串通过AddOverlay接口进行添加:另一种是通过在地图上鼠标单击进行绘制(鼠标绘制工具条库).目前这两种方式只能绘制多折线,并 ...
- CreateProcessW记录
STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; si.dwFlags = STARTF_USESHOWWINDOW; si.wSh ...
- node.js 包教不包会 (Windows版详解)
针对@alsotang 的新手入门教程 https://github.com/alsotang/node-lessons ,详解该教程在Windows中的实践,包括博主在实践过程中遇到的问题及解决方案 ...
- PAT1038. Recover the Smallest Number
//意识到一个重要错误,一直以为atoi,itoa是windows独有的,linux下不可用,直到刚刚... //string+=比strcat好用多了,字符比较也方便的多,但是用scanf读入str ...
- cacti yum快速部署
简述:本来是编译安装的,由于编译过程中库文件关联太多,安装文件一定要有顺序性,报错太多,到了rrdtool这一步说什么都安装不过去了,由于时间问 题,选择了yum安装,对于编译安装,这个要简单多了,她 ...