一、Static、const、extern區別
-------------------------------STATIC--------------------------------
static 全局的,可以改的,如果在一個類中聲明static,類中其他地方用到的時候,也是使用的改變量。但不能用類名直接訪問。
static 全局變量只能在一個文件中使用,也即是說不可能用extern 使它支持外部引用,而全局變量則可以通過extern 在外部文件中引用,
在真正的開發中,一般要使用的是static 全局變量,爲了防此全局變量名相同時而被別的開發小組用extern引用!
.h中
OC中的全局變量,(生命週期)從定義變量的那一行直到文件結束
方法1:使用靜態變量 (不推薦)
方法2: 使用單例模式(static A *a = nil;)
方法3:把全局變量設置到AppDelegate中(實際也是單例)
對於一個完整的程序,內存中的分佈情況:
==========
| 代碼區 |
------------------
| 全局數據區 |(靜態存儲區)
------------------
| 堆區 |
-----------------
| 棧區 |
==========
一般程序的由alloc產生的動態數據存放在堆區,函數內部的自動變量存放在棧區,全局變量和static變量放在全局數據區
static的作用主要有以下3個:
1、擴展生存期;
2、限制作用域;
3、唯一性
OC
局部變量
作用域: 從定義的那一行開始,直到大括號結束或者遇到break return爲止
存儲位置: 棧
全局變量:
作用域:從定義變量的那一行直到文件結束
存儲位置:靜態區
成員變量:
作用域:創建對象時候有效,對象銷燬(釋放)結束
存儲位置:存儲在對象所在的堆內存中
例如:
A類.h
//獲取局部靜態變量staticStr
+ (NSString*)sharedLocalStaticStr;
//獲取全局靜態變量staticStr2
+ (NSString*)sharedGlobalStaticStr;
//改變全局靜態變量staticStr2
+ (NSString*)changeStaticStr;
A類.m
#import “A.h"
staticNSString*staticStr2 =
@"static的使用:全局字符串staticStr2";
@interfaceViewController()
@end
@implementationViewController
//獲取局部靜態變量staticStr
+ (NSString*)sharedLocalStaticStr
{
//局部靜態變量,作用域只限制在此函數,出了這個函數就沒法修改staticStr
static
NSString *staticStr =nil;
if (staticStr ==
nil) {
staticStr =
@"static的使用:全局字符串staticStr";
}
return staticStr;
}
//獲取全局靜態變量staticStr2
+ (NSString*)sharedGlobalStaticStr
{
return
staticStr2;
}
//改變全局靜態變量staticStr2
+ (NSString*)changeStaticStr
{
// staticStr沒法修改因爲它是局部靜態變量;staticStr2k可以修改因爲它是全局靜態變量
staticStr2 =
@"static的使用:全局字符串staticStr2被修改";
return
staticStr2;
}
- (void)viewDidLoad {
[superviewDidLoad];
}
B類.m引用
//打印局部靜態變量
NSLog(@"staticStr = %@",[ViewControllersharedLocalStaticStr]);staticStr
= static的使用:全局字符串staticStr
NSString*staticStr = [ViewControllersharedLocalStaticStr];
staticStr =@"static的使用:全局字符串staticStr被修改";
NSLog(@"staticStr
= %@",[ViewControllersharedLocalStaticStr]);staticStr
= static的使用:全局字符串staticStr
NSLog(@"staticStr
= %@",staticStr);staticStr = static的使用:全局字符串staticStr被修改
//打印全局靜態變量
NSLog(@"staticStr2
= %@",[ViewControllersharedGlobalStaticStr]);staticStr2
= static的使用:全局字符串staticStr2
NSString*staticStr2 = [ViewControllersharedGlobalStaticStr];
staticStr2 =@"static的使用:全局字符串staticStr2被修改";
NSLog(@"staticStr2
= %@",[ViewControllersharedGlobalStaticStr]);staticStr2
= static的使用:全局字符串staticStr2
NSLog(@"staticStr2
= %@",staticStr2);staticStr2 = static的使用:全局字符串staticStr2被修改
NSLog(@"staticStr2 = %@",[ViewControllerchangeStaticStr]);staticStr2
= static的使用:全局字符串staticStr2被修改
STATIC:
一、面向過程設計中的static
1、[靜態全局變量] //在全局變量前,加上關鍵字static,該變量就被定義成爲一個靜態全局變量。
靜態全局變量有以下特點:
1)該變量在全局數據區分配內存;
2)未經初始化的靜態全局變量會被程序自動初始化爲0(自動變量的值是隨機的,除非它被顯式初始化);
3)靜態全局變量在聲明它的整個文件都是可見的,而在文件之外(extern)是不可見的;修改只能通過自己類中得函數修改(+ (NSString*)changeStaticStr
)
定義全局變量就可以實現變量在文件中的共享,但定義靜態全局變量還有以下好處:
1)靜態全局變量不能被其它文件所用;
2)其它文件中可以定義相同名字的變量,不會發生衝突;
2、[靜態局部變量] 在局部變量前,加上關鍵字static,該變量就被定義成爲一個靜態局部變量。
通常,在函數體內定義了一個變量,每當程序運行到該語句時都會給該局部變量分配棧內存。但隨着程序退出函數體,系統就會收回棧內存,局部變量也相應失效。但有時候我們需要在兩次調用之間對變量的值進行保存。通常的想法是定義一個全局變量來實現。但這樣一來,變量已經不再屬於函數本身了,不再僅受函數的控制,給程序的維護帶來不便。
靜態局部變量正好可以解決這個問題。靜態局部變量保存在全局數據區,而不是保存在棧中,每次的值保持到下一次調用,直到下次賦新值。
靜態局部變量有以下特點:
1)該變量在全局數據區分配內存;
2)靜態局部變量在程序執行到該對象的聲明處時被首次初始化,即以後的函數調用不再進行初始化;
3)靜態局部變量一般在聲明處初始化,如果沒有顯式初始化,會被程序自動初始化爲0;
4)它始終駐留在全局數據區,直到程序運行結束。但其作用域爲局部作用域,當定義它的函數或語句塊結束時,其作 用域隨之結束;
3、靜態函數
在函數的返回類型前加上static關鍵字,函數即被定義爲靜態函數。靜態函數與普通函數不同,它只能在聲明它的文件當中可見,不能被其它文件使用。
定義靜態函數的好處:
1)靜態函數不能被其它文件所用;
2)其它文件中可以定義相同名字的函數,不會發生衝突;
二、面向對象的static關鍵字(類中的static關鍵字)
1、靜態數據成員
在類內數據成員的聲明前加上關鍵字static,該數據成員就是類內的靜態數據成員。
靜態數據成員有以下特點:
1)而靜態數據成員被當作是類的成員。無論這個類的對象被定義了多少個,靜態數 據成員在程序中也只有一份拷貝,由該類型的所有對象共享訪問。
2)靜態數據成員存儲在全局數據區,屬於本類的所有對象共享,所以,它不屬於特定的類對象,在沒有產生類對象時其作用域就可見,即在沒有產生類的實例時,我們就可以操作它;
同全局變量相比,使用靜態數據成員有兩個優勢:
1)靜態數據成員沒有進入程序的全局名字空間,因此不存在與程序中其它全局名字衝突的可能性;
2)可以實現[信息隱藏]。靜態數據成員可以是private成員,而全局變量不能;
2、靜態成員函數
它爲類的全部服務而不是爲某一個類的具體對象服務。與普通函數相比,靜態成員函數由於不是與任何的 對象相聯繫,因此它不具有this指針。從這個意義上講,它無法訪問屬於類對象的非靜態數據成員,也無法訪問非靜態成員函數,它只能調用其餘的靜態成員函數。
關於靜態成員函數,可以總結爲以下幾點:
1)出現在類體外的函數定義不能指定關鍵字static;
2)靜態成員之間可以相互訪問,包括靜態成員函數訪問靜態數據成員和訪問靜態成員函數;
3)非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員;
4)靜態成員函數不能訪問非靜態成員函數和非靜態數據成員
--------------------------CONST---------------------------------------
const應用:
一、對於基本聲明
const int r=100;//標準const變量聲明加初始化,編譯器經過類型檢查後直接用100在編譯時替換。
#import"ViewController1.h"
constint
constNum =2;
@interfaceViewController1
()
@end
@implementationViewController1
- (void)viewDidLoad {
[superviewDidLoad];
//
整數常量
NSLog(@"constNum = %d",constNum);constNum
= 2
constNum =
3;(報錯,不讓修改)
}
二、對於指針
1. int x=10; const int *r=&x; //指針指向的內容是常量,r指向的內容不能夠通過r改變,但如果是非const,內容可以通過自己改變,而且r指針可以改變,可以指向其它的整形.
//*r=*r+1;NO //x++;YES //r=&y;YES
2. int const *r=&x; 與1完全相同
3. int * const r=&x; //指針指向是常量,不能修改去指向其它內容,但指向的內容可以修改
//r=&y;NO //*r=*r+1;YES //x++;YES
4.const int * const r=&x; //綜合1、3用法,r是一個指向常量的常量型指針,指針指向不能改變,指針內容不能改變,內容可以自身改變 //r=&y;NO //*r=*r+1;NO //x++;YES
extern
假如A類中已經聲明瞭meString,你在另外一個B類中想使用這個變量,可以extern NSString* meString;會得到a類中同樣的值,且可重新賦值。
//在A.h中聲明兩個字符串
externNSString
*externStr1;
//
定義一個普通的字符串(可以修改),前面加上extern修飾表示該變量可以被其他類導入使用
externNSString
*constexternStr2;//
定義一個不可變字符串(不可以修改)
//在A.m中初始化兩個字符串
NSString*externStr1 =@"extern的使用:普通字符串externStr1";
NSString*constexternStr2
=@"extern的使用:不可變字符串externStr2";
// B類中調用
(1)#import “A.h"
NSLog(@"externStr1
= %@",externStr1);externStr1
= extern的使用:普通字符串externStr1
NSLog(@"externStr2 = %@",externStr2);externStr2
= extern的使用:不可變字符串externStr2
(2)不導入#import “A.h"
externNSString
*externStr1;
externNSString
*const externStr2;
NSLog(@"externStr1 = %@",externStr1);externStr1
= extern的使用:普通字符串externStr1
NSLog(@"externStr2 = %@",externStr2);externStr2
= extern的使用:不可變字符串externStr2
注意:
externStr1=
@"extern的使用:普通字符串externStr1被修改";
NSLog(@"externStr1
= %@",externStr1);externStr1
= extern的使用:普通字符串externStr1被修改
externStr2 =
@"extern的使用:不可變字符串externStr2被修改”;(報錯,常量不能修改)
// 實際開發中
externNSString
*
const
AFNetworkingReachabilityDidChangeNotification;// 設置成常量可以被外部調用,但是外部不允許修改