變數的生命週期、生存空間

2022 / 4 / 16

變數的宣告

每宣告一個變數,它就會被配置一個專屬的記憶體空間

  • 專屬表示記憶體空間不會被挪為他用
  • 記憶體空間有限,你可能會用爆記憶體 

想像一個情境:

在迴圈內重複宣告一個變數

你的記憶體會不會爆開 ?

// Using too many memories ? 
#include<iostream>
using namespace std;

int main() {
    
    while(true){
        int input;
        cin >> input;
        cout << input << endl;
    }
    
}

你覺得記憶體會怎麼配置 ?

1 )

2 )

不同的變數,生存空間(Life Scope)、生存時間(Life Cycle)各不相同

生存空間( Scope ) : 變數可以被使用的程式碼區段

  • 又名   自動變數 ( automatic variable )

區域變數

local variable

2)  同一區塊內不可宣告同名的區域變數

1)  生於宣告,死於出生地的下括號

( Block )

生於宣告,死於出生地的下括號

{
    int a 
    
    /* 其他程式片段 */

}

配置記憶體

釋放記憶體

在變數的可視範圍外不可以使用該變數

#include<iostream>
using namespace std;
int main(){

	
    for(int i = 0 ;i < 10 ; i++){
            
    }
    
    cout << i << endl;


    return 0;
}

謹記

區域變數生於宣告,死於下括號

#include<iostream>
using namespace std;
int main(){

    int a,b;
    cin >> a >> b ;

    if(a > b){
        int tmp = b;
        b = a;
        a = tmp;
    }

    cout << a << ' ' << b << endl;

    return 0;
}

a、b出生

a、b死去

綠色 Scope

tmp 出生

tmp 死去

黃色 Scope

#include<iostream>
using namespace std;
int main(){

    for(int i = 0; i < 5 ; i++){
    
        cout <<< i << ' ';
    
    }

    reutrn 0;
}

i出生

i死去

#include<iostream>
using namespace std;
int main(){

    for(int i = 0; i < 5 ; i++){
    	
        int tmp = i;
        cout << tmp << ' ';
		  
    }

    reutrn 0;
}

tmp 出生

tmp 死去

#include<iostream>
using namespace std;

int add(int x,int y){
    return x + y;
}

int main(){

    int a,b;
    cin >> a >> b ;

    int afterAdd = add(a,b);

    cout << afterAdd << endl;
    
    // compiler會報錯
    cout << x << ' ' << y << endl;
    
    return 0;
}

x、y 出生

x、y 死去

無法被存取的變數不能使用!

#include<iostream>
int* add(int a,int b)
{
     int sum = a + b;

     return &sum;
}

int main() {

    int* addr = add(5, 6);
    std::cout << *addr;

}

1 )     

2 )     

記憶體殘值

5

#include<iostream>
using std::cout;
using std::endl;

int main() {
 
    int num = 1;
    cout << num << endl; 

    num ++;
    
    cout << num << endl; 
    
    {
        num++;
        cout << num << endl; 
    }

    cout << num << endl;  
}

1 )     

2 )     

1

2

3

2

1

2

3

3

// Using too many memories ? 
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
int main() {
    
    while(true){
        int input;
        cin >> input;
        cout << input << endl;
    }
    
}

你覺得記憶體會怎麼配置 ?

1 )

2 )

全域變數

global variable

1 ) 宣告在任何 Block 之外的變數

2) 若沒有賦予初始值,則自動給 0

3) 在程式碼結束前都能使用

4)  任何 Block 都能使用

全域變數的特性

#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int number = 100; //number is a global variable

void PrintInFunction(){
    cout << "In the PrintNumber funciton , number is " << number << endl;
}

int main() {
    cout << "In the main function , number is " << number << endl;
    PrintInFunction();
}

靜態變數

static variable

2) 若沒有賦予初始值,則自動給 0

3) 在程式碼結束前都會佔用記憶體

靜態變數的特性

1) 用關鍵字 static 修飾變數

如同 global variable 一直存在

但 static variable 不能在任何區段存取

#include<iostream>
using namespace std;
int main(){
    
    int static a;      // a = 0
    int static b = 0;  // b = 0
}
#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int count(void){ 
    int static num;
    num += 5;
    return num;
} 

int main() {

    cout << count() << endl;
    cout << count() << endl;
    cout << count() << endl;
    cout << count() << endl;

}

1 )     

2 )     

5

5

5

5

5

10

15

20

3 )     

num沒有初值

答案會是亂數

變數遮蔽

變數遮蔽

當程式碼內變數 撞名 時  

範圍小的變數會暫時遮蔽範圍大的變數

#include<iostream>
using namespace std;

int main() {

    int x = 10;

    {
        int x = 5;
        cout << x << endl;
    }    

    cout << x << endl;

}

黃色區段的變數

遮蔽

綠色區段的變數

#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int main() {

    for(int i = 0; i < 10; i++){
        cout << "i = " << i << "ouside, ";
        for(int i = 0; i< 10 ;i++){
            cout << i*i << ' ';
        }
        cout << endl;
    }

}
#include<iostream>
using std::cout;
using std::endl;

int main() {
 
    int num = 1;
    cout << num << endl; 

    num ++;
    
    cout << num << endl; 
    
    {	
    	int num = 1;
        num++;
        cout << num << endl; 
    }

    cout << num << endl;  
}

1 )     

1

2

2

2

2 )     

1

2

2

3

3 )     

1

2

3

4

namespace scope

每次寫的 using namespace std

是什麼意思 ?

什麼是 using ? 

什麼是 namespace ?

什麼是 std ?

namespace

  • 像是一個收納庫,裡面有變數、函式、類......東西包在裡面

namespace std{

         cin = ...... ;

         cout =   ..... ;

         endl = ...... ;

         vector = ..... ;

         string = ...... ;

         和很多其他東西

}

要使用包含在裡面的 cin、cout、endl

需要加上 " 空間名稱:: " 

#include<iostream>
int main(){
    int x;
    std::cin >> x ;
    std::cout << x << std::endl;
}

三種使用namespace的方法

#include<iostream>
using namespace std;

int main(){

    int x;
    cin >> x ;
    cout << x << endl;



}
#include<iostream>

int main(){


    int x;
    std::cin >> x ;
    std::cout << x << std::endl;



}
#include<iostream>
using std::cin;
using std::cout;
using std::endl;

int main(){

    int x;
    cin >> x ;
    cout << x << endl;

}

糟糕的習慣

為甚麼不要寫 using namespace std  ?

  • std 裡面的成員很多 !
  • 代表你會把 std 裡面所有的成員都 include進來
  • 你在幫變數取名字時可能跟 std 裡的被定義好的成員衝突
#include <iostream>
#include <algorithm>  // std::min
using namespace std;

int min;  // global variable

int main() {
    min = 123;
}

練習題

可以用上節課教的陣列控制方向寫出這題

 

注意 ! !   

  •          每row最後一個數字不用輸出空白
  •          每個row都要加換行

或是你有更棒的寫法也行~

 

int main(){

    int dirc[8][2] = { {0,1},    // 往右
                       {0,-1},   // 往左
                       ......}; // 往左上

    int dr[8] = {0,0,.....},
        dc[8] = {1,-1,....};   
        
}

兩種控制方向的陣列寫法

Life cycle ver.student

By Yei Yang

Life cycle ver.student

  • 262