1. Tham chiếu tới giá trị hằng

Trong bài Con trỏ và hằng, chúng ta đã biết cách khai báo một con trỏ trỏ đến một giá trị hằng, tương tự như vậy, ta cũng có thể khai báo một tham chiếu tới một giá trị hằng. Điều này được thực hiện bằng cách sử dụng từ khóa const khi khai báo tham chiếu:

const int value = 5;
const int &ref = value; // ref is a reference to const value

Một tham chiếu tới một giá trị hằng thường được gọi ngắn gọn là một tham chiếu hằng (const reference), mặc dù điều này dẫn đến một số sự không nhất quán về cách đặt tên với con trỏ.

2. Khởi tạo tham chiếu với các giá trị hằng

Không giống như tham chiếu tới các giá trị không phải là hằng, chỉ có thể được khởi tạo bằng các l-values không phải hằng. tham chiếu tới giá trị hằng có thể được khởi tạo bằng l-value không hằng, l-values hằng, và r-values.

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

int x = 5;
const int &ref1 = x; // okay, x is a non-const l-value
 
const int y = 7;
const int &ref2 = y; // okay, y is a const l-value
 
const int &ref3 = 6; // okay, 6 is an r-value

Giống như một con trỏ trỏ đến một giá trị hằng, một tham chiếu tới một giá trị hằng cũng có thể tham chiếu tới một biến không hằng. Khi được truy cập thông qua một tham chiếu tới một giá trị hằng, giá trị sẽ được coi là hằng kể cả khi biến ban đầu không phải là hằng:

int value = 5;
const int &ref = value; // create const reference to variable value
 
value = 6; // okay, value is non-const
ref = 7; // illegal -- ref is const

3. Tham chiếu tới r-values kéo dài thời gian tồn tại của giá trị được tham chiếu

Thông thường r-values sẽ có các phạm vi biểu thức, nghĩa là các giá trị này sẽ bị hủy khi biểu thức mà chúng được tạo ra bên trong đó kết thúc.

std::cout << 2 + 3; // 2 + 3 evaluates to r-value 5, which is destroyed at the end of this statement

Tuy nhiên, khi một tham chiếu tới một giá trị hằng được khởi tạo với một r-value, thời gian tồn tại (lifetime) của r-value sẽ được kéo dài để phù hợp với thời gian tồn tại của tham chiếu.

int somefcn()
{
    const int &ref = 2 + 3; // normally the result of 2+3 has expression scope and is destroyed at the end of this statement
    // but because the result is now bound to a reference to a const value...
    std::cout << ref; // we can use it here
} // and the lifetime of the r-value is extended to here, when the const reference dies

4. Tham chiếu hằng đóng vai trò làm tham số của hàm

Tham chiếu được sử dụng làm tham số hàm cũng có thể là hằng. Điều này cho phép chúng ta truy cập tới đối số mà không cần tạo ra bản sao nào của nó, trong khi vẫn đảm bảo rằng hàm sẽ không thay đổi giá trị đang được tham chiếu.

// ref is a const reference to the argument passed in, not a copy
void changeN(const int &ref)
{
	ref = 6; // not allowed, ref is const
}

Tham chiếu tới các giá trị hằng đặc biệt hữu ích khi được sử dụng làm tham số hàm bởi vì tính linh hoạt của chúng. Một tham số hàm là tham chiếu hằng cho phép bạn truyền vào một đối số l-value không hằng, một đối số l-value hằng, một giá trị không đổi (literal), hoặc kết quả của một biểu thức.

/**
* Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
*
* @author cafedevn
* Contact: cafedevn@gmail.com
* Fanpage: https://www.facebook.com/cafedevn
* Instagram: https://instagram.com/cafedevn
* Twitter: https://twitter.com/CafedeVn
* Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

#include <iostream>
 
void printIt(const int &x)
{
    std::cout << x;
}
 
int main()
{
    int a = 1;
    printIt(a); // non-const l-value
 
    const int b = 2;
    printIt(b); // const l-value
 
    printIt(3); // literal r-value
 
    printIt(2+b); // expression r-value
 
    return 0;
}

Đoạn code trên sẽ in ra:

1234

Để tránh việc tạo ra các bản sao dữ liệu không cần thiết, có khả năng tiêu tốn nhiều tài nguyên máy tính, các biến mà không phải con trỏ hoặc kiểu dữ liệu cơ bản (int, double, v.v…) thường được truyền vào hàm theo kiểu tham chiếu (hằng). Các kiểu dữ liệu cơ bản nên được truyền theo kiểu giá trị, trừ khi hàm cần thay đổi chúng trong quá trình thực thi.

Quy tắc: Hãy truyền các biến không phải con trỏ, các biến không phải kiểu dữ liệu cơ bản (chằng hạn như structs) theo kiểu tham chiếu (hằng).

Hãy cùng học và ôn luyện kiến thức và kỹ năng lập trình C++ với series TỰ HỌC C++.

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!