C++: Bài 24: Tham chiếu


Đăng ký nhận thông báo về những video mới nhất

Một biến tham chiếu là một bí danh, nghĩa là một tên khác của một biến đã tồn tại. Khi một tham chiếu được khởi tạo với một biến, tên biến hoặc tên tham chiếu có thể được sử dụng để tham chiếu đến biến.

Tham chiếu so với Con trỏ

Tham chiếu thường bị nhầm lẫn với con trỏ nhưng có ba điểm khác biệt chính giữa tham chiếu và con trỏ là như sau:

  • Bạn không thể có tham chiếu NULL. Bạn phải luôn có thể giả định rằng một tham chiếu được kết nối với một phần hợp lệ của bộ lưu trữ.

  • Khi một tham chiếu được khởi tạo cho một đối tượng, nó không thể được thay đổi để tham chiếu đến một đối tượng khác. Con trỏ có thể được trỏ đến một đối tượng khác bất cứ lúc nào.

  • Khi ta tạo tham chiếu thì nó phải được khởi tạo. Con trỏ có thể được khởi tạo bất kỳ lúc nào.

Tạo tham chiếu trong C++

Hãy coi một tên biến như một nhãn gắn với vị trí của biến đó trong bộ nhớ. Sau đó, ta có thể coi một tham chiếu như một nhãn thứ hai được gắn vào vị trí bộ nhớ đó. Do đó, bạn có thể truy cập nội dung của biến thông qua tên biến ban đầu hoặc tham chiếu. Ví dụ:

int i = 17;
double d = 20;

Ta có thể khai báo các biến tham chiếu cho i như sau.

int& r = i;
double& s = d;

& đặt sau int thể hiện việc khai báo tham chiếu, cụ thể "r là tham chiếu số nguyên được khởi tạo thành i" và "s là tham chiếu double được khởi tạo thành d". Ví dụ sau sử dụng các tham chiếu trên kiểu int và double:

#include <iostream>

using namespace std;

main(){
  // khai báo các biến
  int    i;
  double d;

  // khai báo các biến tham chiếu
  int&    r = i;
  double& s = d;

  i = 5;
  cout << "Gia tri cua i: " << i << endl;
  cout << "Gia tri cua tham chieu i: " << r  << endl;

  d = 11.7;
  cout << "Gia tri cua d: " << d << endl;
  cout << "Gia tri cua tham chieu d: " << s  << endl;

  return 0;
}

Khi đoạn mã trên được biên dịch cùng nhau và được thực thi, nó sẽ tạo ra kết quả sau:

Gia tri cua i: 5
Gia tri cua tham chieu i: 5
Gia tri cua d: 11.7
Gia tri cua tham chieu d: 11.7

Tham chiếu thường được sử dụng cho danh sách đối số hàm và giá trị trả về của hàm. Sau đây là hai chủ đề quan trọng liên quan đến tham chiếu trong C++ mà một lập trình viên C++ cần phải nắm rõ:

Tham chiếu dưới dạng tham số

Dưới đây là một ví dụ về lời gọi theo tham chiếu sử dụng tham chiếu trong C++:

#include <iostream>
using namespace std;

// khai báo hàm
void swap(int& x, int& y);

  main() {
  // khai báo các biến local:
  int a = 100;
  int b = 200;

  cout << "Truoc khi swap, a = " << a << endl;
  cout << "Truoc khi swap, b = " << b << endl;

  /* gi mt hàm đ swap các giá tr.*/
  swap(a, b);

  cout << "Sau khi swap, a = " << a << endl;
  cout << "Sau khi swap, b = " << b << endl;

  return 0;
}

// đnh nghĩa hàm đ swap các giá tr.
void swap(int& x, int& y) {
  int temp;
  temp = x; /* ly giá tr ti đa ch x lưu vào temp */
  x = y;    /* lưu y vào x */
  y = temp; /* lưu x vào y (vì temp cha x) */
}

Kết quả thực thi của đoạn code trên:

Truoc khi swap, a = 100
Truoc khi swap, b = 200
Sau khi swap, a = 200
Sau khi swap, b = 100

Tham chiếu dưới dạng giá trị trả về

Một chương trình C++ có thể dễ đọc và dễ bảo trì hơn bằng cách sử dụng tham chiếu thay vì con trỏ. Một hàm trong C++ có thể trả về một tham chiếu theo cách tương tự như nó trả về một con trỏ.

Khi một hàm trả về một tham chiếu, nó sẽ trả về một con trỏ không tường minh đến giá trị trả về của nó. Bằng cách này, một hàm có thể được sử dụng ở bên trái của một câu lệnh gán. Hãy xét chương trình đơn giản sau:

#include<iostream>
#include<ctime>

using namespace std;

double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};

double& setValues(int i) {
  return vals[i]; // tr v mt tham chiếu ti phn t ch s i
}

// hàm main s gi hàm được đnh nghĩa  trên.
main() {

  cout << "Gia tri truoc khi thay doi:" << endl;
  for ( int i = 0; i < 5; i++ ) {
    cout << "vals[" << i << "] = " << vals[i] << endl;
  }

  setValues(1) = 20.23; // thay đi phn t ch s 1
  setValues(3) = 70.8;  // thay đi phn t ch s 3

  cout << "Sau khi thay doi:" << endl;
  for ( int i = 0; i < 5; i++ ) {
    cout << "vals[" << i << "] = " << vals[i] << endl;
  }
  return 0;
}

Khi đoạn mã trên được biên dịch cùng nhau và được thực thi, nó sẽ tạo ra kết quả sau:

Gia tri truoc khi thay doi:
vals[0] = 10.1
vals[1] = 12.6
vals[2] = 33.1
vals[3] = 24.1
vals[4] = 50
Sau khi thay doi:
vals[0] = 10.1
vals[1] = 20.23
vals[2] = 33.1
vals[3] = 70.8
vals[4] = 50

Khi trả về một tham chiếu, hãy lưu ý rằng đối tượng được tham chiếu không được nằm ngoài phạm vi. Vì vậy, việc trả về một tham chiếu đến biến local là không hợp lệ. Nhưng bạn luôn có thể trả về một tham chiếu trên một biến tĩnh.

int& func() {
  int q;
  // return q; // li thi gian biên dch
  static int x;
  return x;    // an toàn, x tn ti ngoài phm vi
}

Nếu bạn có điều thắc mắc, bạn hãy comment cho V1Study để được giải đáp.
Bài viết này được chia sẻ bởi LongDT. Nếu bạn muốn chia sẻ bài viết, bạn hãy Đăng ký làm thành viên!
« Prev
Next »
Copied !!!