//
you're reading...
C Plus Plus, Codes

Cách sử dụng “const” trong C++

Nhiều khi đụng tới const trong C++, tôi gặp phải một số khó khăn vì việc nhầm lẫn giữa cách sử dụng const trong từng trường hợp cụ thể. Cho nên tôi đã tìm và đọc lại một số bài viết về vấn đề này trên mạng thì vấn đề đã trở nên đơn giản hơn nhiều. Dưới đây là một bài viết khá hay về vấn đề này, sưu tầm từ blog phongtran88.wordpress.com:

Điều đầu tiên khi lập trình viên nghĩ đến từ khóa const là những gì không thể thay đổi được (hằng số). Bạn không thể thay đổi giá trị của một hằng số. Bạn có thể dùng từ khóa const để chỉ ra rằng một giá trị nào đó sẽ không thể thay đổi được trong suốt chương trình của bạn. Một câu hỏi dành cho bạn:

Bạn có thể đặt từ khóa “const” ở những nơi nào trong chương trình của mình?

Để trả lời câu hỏi trên khi làm việc với ngôn ngữ lập trình (ở đây là C++), bạn cần phải trả lời được câu hỏi: “Tôi cần giá trị nào trở thành không thay đổi được?”.

Ở đây, trong bài viết này, xin liệt kê ra một số nơi bạn có thể đặt từ const.

1. Khi khai báo một biến, nếu bạn đặt thêm từ const thì giá trị của biến đó sẽ không thể thay đổi được trong suốt phạm vi tồn tại của biến đó.
Ví dụ các khai báo sau:

const int x = 8;
int const y = 10;

Hai dạng khai báo trên là tương đương. Giá trị của hai biến x và y sẽ không thể thay đổi được.

2. Đối với biến con trỏ, bạn cần lưu ý đến hai điều: vùng nhớ con trỏ trỏ đến và giá trị của vùng nhớ đó.

Với các khai báo:

int x = 10, y = 20;
const int *px = &x;

Khi này, giá trị của vùng nhớ mà px đang trỏ đến là không thể thay đổi được thông qua thay đổi (*px). Do đó, ta có các câu lệnh sau:

*px = 15; // incorrect
px = &y; // correct
x = 15; // correct

(Để ý rằng giá trị của x vẫn có thể được thay đổi, ta chỉ không thể thay đổi giá trị này thông qua px)

Nhưng với các khai báo sau:

int x = 10, y = 20;
int* const px = &x;

Khi này, giá trị của vùng nhớ mà px trỏ đến có thể được thay đổi thông qua việc thay đổi (*px) nhưng điều đặc biệt là ta không thể làm cho px trỏ đến một vùng nhớ khác. Ta có các câu lệnh sau:

*px = 15; // correct
px = &y; // incorrect

Với khai báo sau:

int x = 10;
const int* const px = &x;

Bạn không thể thay đổi nơi px đang trỏ đến và thông qua (*px) cũng không thể thay đổi giá trị vùng nhớ đó.

 

Tiếp theo bài viết kỳ trước, bài này xin trình bày tác dụng của const khi hoạt động với hàm trong C++.

Giả sử ta có cấu trúc sau:

class A
{
private:

int m_a;

public:

     …
};

Và ta có một hàm nhận tham số đầu vào là một đối tượng kiểu A và trả về một đối tượng kiểu A.

A functionName(A object);  // object là một đối tượng kiểu A

Khi gọi hàm này với x là một đối tượng kiểu A:

functionName(x);

Một đối tượng object sẽ được tạo và máy sẽ copy toàn bộ giá trị của x vào object rồi xử lý, sau đó sẽ trả về một đối tượng kiểu A. Vấn đề phát sinh là khi ta có một class với kích thước lớn thì việc chép giá trị vào tham số hình thức ở hàm sẽ làm cho chương trình trở nên chậm đi và đặc biệt là sẽ hao phí bộ nhớ. Do đó, ta có giải pháp là hai khai báo cho hàm đó như sau:

A functionName(A& object);
A functionName(A* object);

Hàm trên sử dụng tham số hình thức là một biến tham chiếu (reference variable) và hàm dưới dùng một biến con trỏ (pointer variable). Hai cách khai báo này sẽ cho kết quả tương tự nhau. (Sự khác nhau giữa biến tham chiếu và biến con trỏ sẽ được trình bày trong một bài gần đây). Khi này, với lời gọi hàm như trên thì địa chỉ của x sẽ được truyền vào, do đó sẽ tránh được việc phải chép cả cấu trúc với kích thước lớn.

Nhưng với khai báo như thế thì giá trị của biến truyền vào có thể bị thay đổi thông qua biến object (vì là biến con trỏ hoặc tham chiếu), trong khi với cách khai báo như cũ thì ta không hề muốn giá trị này bị sửa đổi chút nào. Do đó, từ khóa const được sử dụng:

A functionName(const A& object);
A functionName(const A* object);

Như bài trước, nếu ta muốn con trỏ object luôn trỏ đến một vị trí cố định thì hãy viết:

A functionName(const A* const object);

Nếu hàm trả về một con trỏ trỏ đến một đối tượng kiểu A:

A* functionName(const A* const object);

Theo nhu cầu, có thể bạn mong muốn hàm sẽ trả về con trỏ mà giá trị trỏ đến là không thay đổi được thông qua con trỏ, bạn sẽ khai báo hàm như sau:

const A* functionName(const A* const object);

Nếu bạn muốn con trỏ trả về cũng không thể thay đổi được vị trí trỏ đến của nó thì hãy viết:

const A* const functionName(const A* const object);

Tiếp theo, nếu class A của chúng ta có thêm một phương thức là long A::m_square() ; chẳng hạn. Phương thức này sẽ tính bình phương của biến A::m_a và trả về giá trị đó. Thực sự, đây chỉ là một hàm tính toán một giá trị từ giá trị của những thuộc tính trong class. Yêu cầu đặt ra là hàm này không được làm thay đổi giá trị của các thuộc tính của class. Do đó ta sẽ sử dụng một phương thức hằng bằng cách đặt từ const vào cuối hàm:

long A::m_square() const;

Bây giờ, nếu bạn lại muốn phương thức hằng của mình vẫn có thể thay đổi được giá trị của một số thuộc tính của class thì sao? Điều này vẫn có thể đạt được bằng cách sử dụng từ khóa mutable vào trước khai báo của thuộc tính nào bạn cần thay đổi giá trị bởi phương thức hằng. Chú ý là mutable không được dùng cho các biến staticconst.

Trở lại với hàm functionName(…) của ta. Khi hàm này là một phương thức của class A và bạn muốn nó trở thành một phương thức hằng thì ta có một khai báo khủng hoảng về từ khóa const:

const A* const functionName(const A* const object) const; // 5 từ const

Việc sử dụng những từ khoá const và vị trí của chúng trong chương trình là tùy theo mục đích và yêu cầu của ngữ cảnh hiện tại. Do đó, bạn hãy lưu ý khi làm việc với chúng.

– Phong Tran –

Advertisements

Discussion

One thought on “Cách sử dụng “const” trong C++

  1. Good job. Thanks for sharing

    Posted by Binh Duong | 28.10.2010, 11:55

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: