Search…

Sự Khác Biệt Giữa const và constexpr

20/09/20204 min read
Tìm hiểu về sự khác biệt giữa const và constexpr trong C++.

Nhắc lại về const

Từ khóa const (constant – hằng) là từ khóa để chỉ định một biến hay đối tượng là hằng, tức là không thay đổi được giá trị, mọi hành động thay đổi giá trị của hằng đều được compiler báo lỗi. Mục đích của const để tăng ràng buộc khi 1 biến thay đổi sẽ gây ra các hiệu ứng phụ cho chương trình.

Ví dụ khi truyền tham số dạng tham chiếu đường dẫn file vào hàm lấy nội dung của file, mục đích của hàm này chỉ sử dụng nội dung từ đường dẫn để lấy được nội dung file, nếu không ràng buộc const có thể dẫn đến các sơ sót do vô ý thay đổi giá trị đường dẫn và có thể trong chương trình có 1 đoạn mã cần sử dụng lại giá trị này nhưng không còn đúng nữa.

const được dùng trong các trường hợp đối tượng là biến tham trị, biến tham chiếu và tham số của hàm.

int main()
{
	// Biến thông thường.
	const int x = 7;

	// Biến tham chiếu
	int y = 8;
	const int &A = y;

	// Biến con trỏ
	int z = 9;
	int *const p = &x;

	return 0;
}

// Tham số của hàm
void printName(const char * ID)
{
	// phần xử lý.
}

Bài viết không đi sâu vào phân tích const, nếu cần chi tiết hơn có thể xem bài Thao Tác Với Constant trong C++.

Khái niệm constexpr

constexpr được giới thiệu ở C++11 có chức năng yêu cầu trình biên dịch tính toán hàm hoặc biến tại thời điểm biên dịch. Các biến và hàm này được quy đổi thành 1 giá trị cố định khi biên dịch nên giảm được thời gian thực thi.

constexpr variable

Khi khai báo một biến constexprconst cũng được hiểu là không thể thay đổi giá trị, nhưng khác là constexpr phải đủ điều kiện để tính toán được trong thời điểm biên dịch, còn const sẽ thuộc thời gian thực thi. Muốn sử dụng constexpr cần phải tuân theo những quy định sau:

  • Kiểu của biến được thể hiện phải là LiteralType.
  • Nó cần được khởi tạo ngay tại thời điểm định nghĩa biến.
constexpr int a = 2;

constexpr function

Khi khai báo 1 hàm là constexpr function, hàm này phải thỏa các điều kiện:

  • Nó không phải là virtual function.
  • Kiểu trả về của hàm phải là LiteralType.
  • Các biến tham số của hàm phải là LiteralType.
constexpr int add(int a, int b)
{
	return a + b;
}

constexpr và thời gian biên dịch

Điều quan trọng nhất của constexpr là biểu thức được tính tại thời gian biên dịch:

int add_vectors_size(const std::vector<int> & a, const std::vector<int> & b)  
{
	return a.size() + b.size();
}

Như đã làm với hàm add phía trên, chuyển hàm add_vectors_size về dạng constexpr:

constexpr int add_vectors_size(const std::vector<int> & a, const std::vector<int> & b)  
{
	return a.size() + b.size();
}

Tuy nhiên, cách làm này là không chính xác, vì tại thời điểm biên dịch, tham số truyền vào là 2 vector, trình biên dịch sẽ không biết kích thước của 2 vector đó, vậy nên hàm này không tính trước được.

Đối với một ví dụ khác:

template <std::size_t N1, std::size_t N2>
int add_arrays_size(const std::array<int, N1> & a,
                    const std::array<int, N2> & b)
{
	return a.size() + b.size();
}

Hàm này lại có thể hoàn toàn thực hiện được, do tại thời điểm biên dịch, trình biên dịch biết được kích thước của hai mảng ab.

Lời kết

Trong lịch sử phát triển của C++, những lập trình viên hỗ trợ xây dựng lên C++ ngày càng hoàn thiện hơn, cải tiến tốc độ biên dịch là yếu tố rất được quan tâm đến. Từ đó qua các thế hệ C++ tiêu biểu như C++98, C++11, C++14 và tiếp đến là C++17, xuất hiện nhiều hơn các từ khóa mới, khái niệm mới nhầm tối ưu hóa tốc độ và bộ nhớ song song với khả năng phát triển phần mềm tiện lợi, việc của lập trình viên là tiếp tục cập nhật những cải tiến này.

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024