Const trong c++ là gì

Vòng loại const có nghĩa là một biến/con trỏ được xác định là const có thể không bị thay đổi bởi chương trình của bạn và nó sẽ nhận được giá trị của nó từ khởi tạo rõ ràng hoặc bằng phương tiện phụ thuộc vào phần cứng.

Một con trỏ được định nghĩa là const trong khai báo tham số, mã chức năng sẽ không sửa đổi những gì nó trỏ đến. Về cơ bản, bạn có thể sử dụng con trỏ và nó có khá nhiều chức năng như là "chỉ đọc". 

Ví dụ:-

void foo(const char *x) { while(*x) { if(*x==' ') cout << '-'; //printing - when a space is encountered else cout << *x; x++; } }

Các chức năng trên là tốt và sẽ không hiển thị bất kỳ lỗi. Nhưng nếu foo có bất cứ điều gì có thể thay đổi chuỗi được thông qua. nói một hàm thay thế khoảng trắng bằng $. Không in $ nhưng thay đổi thành $. Một cái gì đó như thế này: -

void foo(const char *x) { while(*x) { if(*x==' ') *x = '$'; //printing - when a space is encountered else cout << *x; x++; } }

sau đó nó sẽ không biên dịch tức là lỗi gán cho vị trí bộ nhớ chỉ đọc.

Như đã nói ở vấn đề trước Xử lý nhiều tiến trình cùng một lúc trên Arduino - Có thể hay không?, chúng ta có thể xử lý nhiều tiến trình trên Arduino theo cơ chế bất đồng bộ. Tuy nhiên, một vấn đề khá hay mà từ các bình luận ở bài viết đó, mình mới ngộ ra được, đó là làm thế nào để xây dựng một quy trình công việc thực sự trên một board mạch Arduino. Thiết nghĩ, điều đó, hoàn toàn có thể thực hiện được, và xin chia sẻ với mọi người qua bài viết này nhằm giúp tất cả chúng ta có một thư viện chuẩn để làm những công việc phức tạp hơn.

Rate node

Rate node

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 –

1

Bạn đang thắc mắc? Ghi câu hỏi của bạn và đăng ở chế độ cộng đồng (?)

Cho mình hỏi về tác dụng của const trong các khai báo hàm sau:

const int func(int value); int func(const int value); int func(int value) const; int func(int const value);

1 Like

int func(int value) const;
có nghĩa là các tham số đưa vào hàm func ở dạng tham biến hay tham chiếu thì đều k được thay đổi giá trị của các biến đó, chỉ được đọc giá trị, cái này thường dùng khi tham số vào hàm là tham biến hoặc tham chiếu, còn tham trị như ví dụ bạn viết trên thì k cần, vì tham trị thực chất là nó tạo ra 1 biến mới lưu giữ giá trị của biến đưa vào hàm phục vụ cho riêng hàm đó, dùng xong hàm biến đó sẽ tự được dọn dẹp ( có thể dùng ở trường hợp truyền vào 1 sô và chỉ muốn hàm đó dùng giá trị đó, k được thay giá trị (phạm vị hàm))

int func(const int value); tương đương int func(int const value);
thì khác hơn cái trên 1 chút, nãy viết int func(int value1, int value2) const; thì có nghĩa tất cả các tham số đầu vào đều k được thay đổi, còn viết int func(const int value1, int value2); thì chỉ mỗi value1 k được thay đổi, còn value 2 có thể thay đổi , cũng như trên, cái này chỉ dùng khi tham sô vào hàm là tham chiếu hoặc tham biến, tham trị k cần dùng ( có thể dùng ở trường hợp truyền vào 1 sô và chỉ muốn hàm đó dùng giá trị đó, k được thay giá trị (phạm vị hàm))

Là biến hằng (không thể thay đổi đó mà)

@hell6w9rld 1: sai nhé

Const trong c++ là gì
Vincent_Viet:

const int func(int value);

Giá trị trả về của hàm phải là const

Const trong c++ là gì
Vincent_Viet:

int func(const int value); …

int func(int const value);

2 thằng này là 1, value sẽ không thể thay đổi giá trị trong hàm, bát kể là tham biến hay tham trị, thường dùng cho setValue(const int value)

Const trong c++ là gì
Vincent_Viet:

int func(int value) const;

Thằng này chỉ dùng trong class, struct, các biến của nó không được phép thay đổi trong function đó.
VD:

class MyClass { int id; int getId() const { this->id = 1; // báo lỗi return this->id; } };

như trên thì m chỉ sai mỗi cái đầu
const int func(int value);
nhỉ

int func(int value) const;

Bạn hiểu sai thằng này

Còn thằng

const int func(int value);

thì những phiên bản gần đây của C++ không khuyến khích sử dụng.

Const trong c++ là gì
Dark.Hades:

int func(int value) const;

Bạn hiểu sai thằng này

int func(int value) const;
có nghĩa là các tham số đưa vào hàm func ở dạng tham biến hay tham chiếu, tham trị thì đều k được thay đổi giá trị của các biến đó, chỉ được đọc giá trị, cái này thường dùng khi tham số vào hàm là tham biến hoặc tham chiếu, còn tham trị như ví dụ bạn viết trên thì k cần, vì tham trị thực chất là nó tạo ra 1 biến mới lưu giữ giá trị của biến đưa vào hàm phục vụ cho riêng hàm đó, dùng xong hàm biến đó sẽ tự được dọn dẹp ( có thể dùng ở trường hợp truyền vào 1 sô và chỉ muốn hàm đó dùng giá trị đó, k được thay giá trị (phạm vị hàm))

kiểu viết trên qua c++ học m mới thầy, có nghĩa là mở rộng của c++ so với c.

Bạn vào link này, tất cả code lỗi đều ở đây:

wandbox.org

#include #include class MyClass { int id; // const int getId() { const int i = 1; return i; } int setId(const int &id) { id = 1; } int getI

// int func() const {} chỉ dùng cho OOP

1 Like

Home Categories FAQ/Guidelines Terms of Service Privacy Policy