Hướng dẫn biến toàn cục c++

Trong ví dụ 1, ta định nghĩa hàm func() trước cả đặt biến toàn cục s = “hello world”. Hàm func() cần hiểu s sẽ là một biến toàn cục ở đâu đó bên ngoài hàm func()

def func():
    print s
s = "hello world"
func()

Output:

hello world

Trong ví dụ 2, ta thấy trong func() có thêm một biến địa phương s, func() sẽ nhận giá trị của biến địa phương này thay vì biến toàn cục phía bên ngoài. Ta thấy rằng hai biến toàn cục và biến địa phương cùng tên trong hàm func() không ảnh hưởng gì đến nhau.

def func():
    s = "it's me"
    print s
s = "hello world"
func()
print "s = ",s

Output:

it's me

s =  hello world

Trong ví dụ 3, ta thấy chương trình báo lỗi “UnboundLocalError: local variable 's' referenced before assignment”. Python "giả định" rằng chúng ta muốn có một biến địa phương do việc gán bên trong của hàm func_err (), do đó câu lệnh print đầu tiên đưa ra thông báo lỗi này. Bất kỳ biến được thay đổi hoặc tạo ra bên trong một hàm là biến địa phương, nếu nó không được khai báo như một biến toàn cục.

def func_err():
    print s
    s = "it's me"
    print s

s = "hello world"
func_err()

Output

Traceback (most recent call last):

  File "", line 1, in 

  File "", line 2, in func_err

UnboundLocalError: local variable 's' referenced before assignment

Ví dụ 4. Sửa lỗi cho ví dụ 3, để nói với Python, chúng ta muốn sử dụng biến toàn cục, chúng ta phải sử dụng từ khóa "global", như trong ví dụ 4 sau:

def func_fix():
    global s
    print s
    s = "it's me"
    print s


s = "hello world"
func_fix()

Output:

hello world

it's me

Ví dụ 5 mô tả biến địa phương không thể truy cập sau khi ra khỏi scope của nó.

def    func():
    ss = "it's me"
    print ss

func()
print ss

Output:

it's me

Traceback (most recent call last):

  File "C:/Users/cuongtran/PycharmProjects/BigData/course.py", line 6, in 

    print ss

NameError: name 'ss' is not defined

Ví dụ 6: Tổng hợp của việc sử dụng biến địa phương và biến toàn cục

def func(x,y):

    global a

    a = 1

    x = y+1

    b = 2

    print a,b,x,y



a,b,x,y = 3,4,5,6

func(7,8)

print a,b,x,y


Output


1 2 9 8

1 4 5 6

Kết Luận

Như vậy cái tên nói lên tất cả. Biến toàn cục và biến địa phương khác nhau ở chính phạm vi mà nó được sử dụng trong chương trình. Biến địa phương sẽ chỉ được sử dụng bên trong phạm vi hàm và không thể truy cập được khi ra khỏi phạm vi đó. Ngược lại biến toàn cục được sử dụng trong toàn bộ chương trình, được đặt bên ngoài hàm và nếu một hàm muốn truy cập vào biến toàn cục thì cần khai báo lại biến trong hàm với từ khóa “global”.

Trong các bài học trước, chúng ta đã cùng nhau tìm hiểu cách sử dụng biến (variable) gồm có cách khai báo, khởi tạo, nhập giá trị từ bàn phím và đưa vào biến, tính toán giá trị của biến và đưa giá trị của biến lên màn hình...

Khi một biến được khai báo, hệ điều hành sẽ cấp phát cho chương trình một vùng nhớ có độ lớn tương ứng với độ lớn kiểu dữ liệu của biến.

Hướng dẫn biến toàn cục c++

0.png801x365

Vấn đề là không phải chỉ có một mình chương trình mà các bạn đang viết sử dụng các vùng nhớ trên RAM, mà còn nhiều chương trình khác đang chạy ngầm nữa.

Hướng dẫn biến toàn cục c++

1.png656x597

Trong khi đó, bộ nhớ RAM của chúng ta chỉ có giới hạn. Vì thế, một khi biến (variable) không còn giá trị sử dụng nữa, chúng phải được tiêu hủy để trả lại vùng nhớ mà nó đang giữ, để cấp phát cho những ứng dụng khác cần sử dụng bộ nhớ.

Khi bạn kiểm soát được việc lúc nào cần khai báo biến, khi nào cần tiêu hủy biến sẽ giúp bạn quản lý tài nguyên máy tính tốt hơn. Điều này cần kĩ năng tổ chức và thiết kế chương trình, một kĩ năng quan trọng cần có thời gian để rèn luyện.

Trong bài học này, chúng ta sẽ tìm hiểu hai khái niệm luôn luôn gắn liền với biến (variable):

  • Phạm vi của biến.
  • Thời gian tồn tại của biến.

Hai khái niệm này thường có liên kết chặt chẽ với nhau.

Phạm vi của biến

Phạm vi của biến xác định nơi chúng ta có thể truy cập vào biến.

  • Biến được khai báo bên trong khối lệnh (block) được gọi là biến cục bộ (local variable).

Chương trình bên dưới minh họa cho việc khai báo biến cục bộ, truy cập và truy xuất giá trị của biến cục bộ.

Hướng dẫn biến toàn cục c++

2.png719x329

Biến local variable được khai báo bên trong khối lệnh của hàm main, nên các câu lệnh truy xuất đến biến local variable hoàn toàn hợp lệ.

Một khối lệnh có thể chứa nhiều khối lệnh con khác nhau. Ví dụ:

Hướng dẫn biến toàn cục c++

3.png800x450

Trong đoạn chương trình trên, chúng ta có thêm một khối lệnh nằm bên trong khối lệnh của hàm main, và xuất hiện một biến có tên local variable 2 được khai báo bên trong nó. Ở trong khối lệnh con này (khối lệnh nằm trong khổi lệnh của hàm main) chúng ta có thể truy xuất giá trị của biến local variable 2 như mình đã làm thông qua dòng lệnh

cout << "local_variable2: " << local_variable2 << endl;

để in giá trị của biến local variable 2 lên màn hình. Ngoài ra, mình còn sử dụng phép gán (với toán tử "=") để sửa đổi giá trị cho biến local variable 1 vốn được định nghĩa bên ngoài khối lệnh con.

Điều này có nghĩa là chúng ta có thể truy cập đến một biến đã được khai báo trong những khối lệnh con bên dưới biến đó nếu những khối lệnh con này cũng được đặt trong khối lệnh chứa biến được khai báo.

Khi các bạn sử dụng các khối lệnh con, bạn có thể đặt tên biến trùng với biến được khai báo trong khối lệnh bên ngoài mà nó chứa khối lệnh con đó. Các bạn nhìn vào chương trình bên dưới để thấy rõ hơn:

Hướng dẫn biến toàn cục c++

4.png817x394

Chương trình trên không hề vi phạm quy tắc đặt tên biến mà mình đã nói ở những bài trước.

Trong cùng một khối lệnh không được phép có hai biến trùng tên.

Trong chương trình trên, hai biến number of employees hoàn toàn được khai báo trong hai khối lệnh khác nhau. Bây giờ chúng ta chạy thử chương trình xem kết quả in ra trên màn hình như thế nào.

Hướng dẫn biến toàn cục c++

Như các bạn cũng đã thấy, khi mình thực hiện truy xuất giá trị của biến number of employees bên trong khối lệnh con thì chỉ lấy được giá trị của biến được khai báo bên trong khối lệnh con đó. Tương tự, khi mình thực hiện truy xuất giá trị của biến number of employees của khối lệnh sau hàm main thì chỉ lấy được giá trị của biến được khai báo trong khối lệnh sau hàm main.

Việc đặt tên biến trùng nhau trong nhiều khối lệnh lồng nhau được compiler của Visual studio cho phép, nhưng mình khuyên các bạn nên nghĩ ra một tên biến khác phù hợp hơn để tránh việc nhầm lẫn khi thiết kế một chương trình có quy mô lớn.

  • Biến được khai báo bên ngoài khối lệnh được gọi là biến toàn cục (global variable).

Các bạn cùng nhìn vào đoạn chương trình mẫu bên dưới để xem cách mình khai báo một biến toàn cục như thế nào.

Hướng dẫn biến toàn cục c++

6.png711x312

Như các bạn thấy, mình không đặt dòng khai báo biến bên trong khối lệnh của hàm main nữa mà mình đặt nó bên ngoài và nằm trên khối lệnh của hàm main.

Trong bài học đầu tiên, mình có nói về việc khối lệnh của hàm main sẽ là nơi mà chương trình bắt đầu thực thi, ngoại trừ một số câu lệnh đặc biệt có thể đặt ngoài khối lệnh (khai báo biến, include thư viện, gọi namespace, định nghĩa các class, ...).

Khi có một biến khác nằm trong phạm vi của khối lệnh hàm main được khai báo cùng tên với biến toàn cục bên ngoài khối lệnh hàm main, mỗi câu lệnh truy xuất đến biến đó đều được ưu tiên tìm đến biến cục bộ bên trong hàm main trước. Vậy có cách nào để ta truy xuất được biến toàn cục bên ngoài hàm main không?

Câu trả lời là có! Chúng ta sử dụng toán tử phạm vi (::) như sau:

#include 
using namespace std;

int value = 1;

int main()	{

	int value = 10;

	cout << "local value: " << value << endl;
	cout << "global value: " << ::value << endl;
	
	system("pause");
	return 0;
}

Các bạn thử chạy đoạn code trên xem chương trình thông báo kết quả như thế nào nhé.

Một khi biến toàn cục đã được khai báo, chúng có thể được truy cập tại mọi khối lệnh nằm bên dưới nó. Trong khi đó, biến cục bộ chỉ được phép truy cập khi dòng lệnh còn đặt bên trong khối lệnh chứa nó. Ví dụ:

Hướng dẫn biến toàn cục c++

7.png831x424

Chương trình báo lỗi biến local_variable không được khai báo trước đó trong khi mình đã khai báo bên trong khối lệnh con của khối lệnh hàm main.

Nguyên nhân là do biến local_variable đã bị tiêu hủy trước khi mình kịp truy xuất đến nó.

Thời gian tồn tại của biến

Đối với những biến cục bộ (local variable) có kiểu dữ liệu thông thường như các bạn đã học trong những bài trước, vùng nhớ của biến sẽ tự động giải phóng khi ra khỏi khối lệnh chứa nó.

Hướng dẫn biến toàn cục c++

8.png899x312

Việc cố gắng truy cập đến một biến đã bị hủy sẽ gây nên lỗi. Thời gian tồn tại của biến cục bộ phụ thuộc vào của khối lệnh chứa nó.

Đối với biến toàn cục (được khai báo bên ngoài khối lệnh của hàm main), nó sẽ tồn tại cho đến khi chương trình kết thúc hoặc bị kết thúc bởi người dùng.

Vì thế, các bạn chỉ nên sử dụng biến toàn cục khi cần thiết, để tránh việc vùng nhớ của biến toàn cục được cấp phát nhưng bị chiếm giữ quá lâu gây ảnh hưởng đến việc cấp phát bộ nhớ cho những chương trình khác.


Tổng kết

  • Biến cục bộ được khai báo bên trong khối lệnh. Những biến này chỉ được phép truy cập ở bên trong khối lệnh đó. Biến cục bộ sẽ bị hủy tại thời điểm kết thúc khối lệnh.

  • Biến toàn cục được khai báo bên ngoài khối lệnh. Những biến này được phép truy cập trong mọi khối lệnh nằm bên dưới nó. Biến toàn cục chỉ bị hủy khi chương trình kết thúc.