[Basic] Phạm vi truy cập biến trong C++

Blocks

Block của các câu lệnh là 1 nhóm các câu lênh được trình biên dịch xử lý giống như nó 1 lệnh đơn.

Blocks bắt đầu với dấu { và kết thúc với dấu }.

Blocks có thể được sử dụng ở bất cứ chỗ nào mà ở đó câu lệnh đơn có thể sử dụng được.

ví dụ:

int Add (int a, int b)
{ //Start a block
   
   return a + b;

} //end a block.

Một block có thể đặt trong 1 block khác ( gọi là nested block)

#include <iostream>
using namespace std;

int main()
{ // Start block main function
   int val;
   
   cout << "Enter number : ";
   
   cin >> val;
   
   if (val % 2 == 0)
   { // start nested block
      
      cout << "even number" << endl;
   
   } // end nested block
   else
   {
      cout << "odd number" << endl;
   }
   return 0;

} // end block main

Phạm vi biến (variable scope)

Xác định phạm vi mà ta có thể truy cập biến, ta không thể sử dụng biến ngoài phạm vi truy cập của biến.

Trong C++ ta chú ý đến 2 phạm vi của biến :

Biến cục bộ:

Ta chỉ có thể truy cập biến trong block mà biến được định nghĩa và các nested block của block đó.

Biến toán cục:

Là biến không được khai báo trong block nào, Ta xét 2 phạm vi truy cập của biến toàn cục.

  • Internal linkage : là biến được sử dụng trong file mà nó được định nghĩa, không thể sử dụng ngoài file nó đã được định nghĩa.
  • External linkage : là biến có thể sử dụng cả trong và ngoài file biến đó được định nghĩa.Biến cục bộ (local variable)

Biến cục bộ (local variable)

Định nghĩa

Là biến được định nghĩa trong block, và được sử dụng trong block mà nó được định nghĩa kể từ vị trí biến đó được định nghĩa đến kết thúc block.

Ví dụ:

int main()
{ 
   int age = 0; // Định nghĩa biến cục bộ age, biến age chỉ được sử dụng trong hàm main. 
   
   return 0;
}

Chú ý:

  • Luôn luôn khởi tạo giá trị ban đầu cho biến cục bộ.
  • Biến cục bộ (được cấp phát bộ nhớ trong stack) sẽ được tự động hủy khi kết thúc block.-
  • Với biến cục bộ được cấp phát bộ nhớ động (trên heap) sẽ không được tự động hủy khi kết thức block, người sử dụng phải tự giải phóng bộ nhớ.
  • Biến cục bộ chỉ có thể truy cập được trong block mà nó được định nghĩa, và các nested block được đặt trong block đó.

Ví dụ:

int main()
{
   int val(0); // Định nghĩa biến val trong hàm main

   { // Start nested block 

      int x(0); // Định nghĩa biến x trong nested block

      //Biến val có thể sử dụng trong nested block này.

   } // end nested block

   //Biến val có thể sử dụng ở đây

   //Biến x KHÔNG thể sử dụng ở đây, vì bị hủy sau khi kết thúc nested block 

   return 0;
}

Variable hiding

Trong 1 block ta không thể định nghĩa 2 biến cùng tên, tuy nhiên với 2 block khác nhau ta có thể khai báo 2 biến cùng tên.

Nếu 2 block đó hoàn toàn tách biệt thì sẽ không có vấn đề, mỗi biến được sử dụng trong 1 block sẽ không ảnh hưởng đến nhau.

Tuy nhiên nếu ta khai báo biến trong outer block và nested block thì sao? Vì biến định nghĩa ở outer block có thể được sử dụng được trong nested block.

Ví dụ:

#include <iostream>
using namespace std;

int main()
{ // outer block
   
   int val = 10; 
   
   { // Start nested block 
      
      int val = 20; 
      
      cout << val << endl; // In ra 20, sử dụng biến val được định nghĩa trong nested block
   
   } // end nested block  
 
   cout << val <<< endl; // in ra 10, sử dụng biến val của outer block 

   return 0; 
} // end outer block

=> Khi đó biến trong nested block sẽ “che” đi biến của outer block.

=> Tránh sử dụng biến trong nested block cùng tên với biến outer block

Câu hỏi : Parameter của hàm có phải là local variable không?

Biến toàn cục (global variable)

Biến được định nghĩa bên ngoài block được gọi là biến toàn cục.Biến toàn cục được tạo khi bắt đầu chương trình và hủy khi kết thúc chương trình.Biến toàn cục thường được định nghĩa ở đầu file.

Ví dụ :

#include <iostream>
using namespace std;

//Định nghĩa biến toàn cục
int g_val;

int main()
{ 
   cout << g_val << endl; 
   
   return 0;
}

Chú ý:

  • Với biến toàn cục khi không khởi tạo giá trị ban đầu nó sẽ có giá trị mặc định với từng kiểu dữ liệu.
int g_val; //biến toàn cục g_val sẽ có giá trị mặc định là 0
  • Biến cục bộ có thể cùng tên với biến toàn cục, khi đó biến cục bộ sẽ che khuất biến toàn cục.

=> Để truy cập đến biến toàn cục ta sử dụng toán tử ::

#include <iostream>
using namespace std;

int val = 10;

int main()
{ 
   int val = 20; 

   cout << "local variable : " << val << endl; 

   cout << "Global variable :" << ::val << endl; 

   return 0;
}

Internal linkage.

Một biến với internal linkage được gọi là internal variable, là biến được sử dụng bất cứ đâu trong file mà nó được định nghĩa nhưng không thể sử dụng nó ngoài file mà nó được định nghĩa.

Ví dụ

File Main.cpp

#include <iostream>
using namespace std;

//Biến g_val là internal variable có thể sử dụng trong file Main.cpp
// Biến g_val không thể sử dụng ngoài file Main.cpp
int g_val;

int main()
{ 
   cout << g_val << endl; 
   
   return 0;
}

External linkage

Một biến với external linkage được gọi là external variable là biến có thể được sử dụng ở file nó được định nghĩa và ở file khác.

=> Để khai báo biến là external ta sử dụng từ khóa “extern

Ví dụ:

File Global.cpp

//Định nghĩa và khởi tạo giá trị biến val.
//Biến val được khai báo trong file Main.cpp
int val = 10;

File Main.cpp

#include <iostream>
using namespace std;

//variable forward declaration:
extern int val;

int main()
{ 
   cout << val << endl; // in ra giá trị 10 
   
   return 0;
}

Chú ý : 

  • Tránh nhầm lẫn giữa khai báo nguyên mẫu (forward declaration) và định nghĩa biến extern.

Ví dụ

//variable forward declaration (Không khởi tạo giá trị ban đâu)
extern int val;

//Định nghĩa biến val ( Có khởi tạo giá trị ban đầu)
extern int val = 10;
  • Với các biến external ta thưởng khai báo trong file .h để sử dụng nhiểu nơi dễ dàng. khi đó ta chỉ cần include file .h.

File Global.h

//variable forward declaration
extern int val;

File Global.cpp

//definition biến val
int val = 10;

File Main.cpp // sử dụng biến val

#include <iostream>
#include "Global.h"
using namespace std;

int main()
{ 
   cout << val << endl; // in ra giá trị 10 
   
   return 0;
}

Biến static

Biến tĩnh (static) là biến mà giá trị của nó sẽ vẫn tồn tại khi thoát khỏi phạm vi của biến.

Biến tĩnh chỉ được khởi tạo ra 1 lần và chúng được duy trì trong suốt chương trình.

Biến tĩnh nếu không được khởi tạo sẽ có giá trị mặc định (không phải giá trị rác).

Ví dụ

#include <iostream>
using namespace std;

void T1()
{ 
   //Khai báo biến static 
   static int val = 1; 
   
   val++;
 
   cout << val <<endl;
}

int main()
{ 
   T1(); 
   
   T1(); 
   
   T1(); 
   
   cin.get(); 
   
   return 0;
}

Kết quả

2
3
4

=> Ta thấy hàm T1 được gọi 3 lần, mỗi lần biến val được định nghĩa và khởi tạo giá trị bằng 1. Tuy nhiên biến val là biến static nên nó chỉ được tạo và khởi tạo lần đầu bằng 1,các lần sau nó sẽ không được khởi tạo lại mà lấy giá trị đã thay đổi trước đó (coi như câu lệnh static int val = 1; của hàm gọi lần sau bị bỏ qua)

Ta xét xem kết quả trường hợp sau như thế nào nhé:

#include <iostream>
using namespace std;

void T1()
{ 
   static int val = 1; 
   
   val++;
 
   cout << val << endl;
}

void T2()
{ 
   static int val = 1; 
   
   val++; 
   
   cout << val << endl;
}

int main()
{ 
   T1(); 
   
   T2(); 
   
   cin.get(); 
   
   return 0;
}

Was this article helpful?

Leave A Comment?