Static、const、extern區別

一、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;// 設置成常量可以被外部調用,但是外部不允許修改


Code:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章