close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

Con trỏ và Tham chiếu trong C++

C và C++ hỗ trợ con trỏ cái mà khác với hầu hết các ngôn ngữ lập trình khác. Các ngôn ngữ khác bao gồm C ++, Java, Python, Ruby, Perl và PHP đều hỗ trợ tham chiếu.

Nhìn bề ngoài, cả hai tham chiếu và con trỏ đều rất giống nhau, cả hai đều được sử dụng để có một biến cung cấp quyền truy cập cho một biến khác. Với việc cả hai đều cung cấp nhiều khả năng giống nhau, người ta thường không rõ điều gì khác biệt giữa các cơ chế khác nhau này. Trong bài viết này, tôi sẽ cố gắng minh họa sự khác biệt giữa con trỏ và tham chiếu.

Con trỏ: Con trỏ là một biến chứa địa chỉ bộ nhớ của một biến khác. Một con trỏ cần được deference với toán tử * để truy cập vào vị trí bộ nhớ mà nó trỏ tới.

Tham chiếu: Một biến tham chiếu là một bí danh, tức là một tên khác của một biến đã tồn tại. Một tham chiếu, giống như một con trỏ, cũng được hiện thựcbằng cách lưu trữ địa chỉ của một đối tượng.
Một tham chiếu có thể được coi là một con trỏ hằng (đừng nhầm với một con trỏ đến một giá trị không đổi!) với tính năng tự động chuyển hướng, tức là trình biên dịch sẽ áp dụng toán tử * cho bạn.

Xem thêm về tham chiếu tại đây.

int i = 3; 
// Một con trỏ đến biến i
// (lưu trữ địa chỉ của i)
int *ptr = &i; 
// Một tham chiếu (bí danh) của i.
int &ref = i;

Sự khác nhau giữa Con trỏ và Tham chiếu

1. Khởi tạo

Một con trỏ có thế được khai báo và khởi tạo đồng thời hoặc trên nhiều dòng.

int a = 10;        
int *p = &a;    
hay
int *p;
p = &a;

Trong khi tham chiếu phải được khởi tạo cùng lúc với khai báo.

int a=10;
int &p=a;  //OK
nhưng
int &p;
p=a;      //NOK

Chú ý: Sự khác biệt này có thể thay đổi từ trình biên dịch này sang trình biên dịch khác. Sự khác biệt trên là đối với Turbo IDE.

2. Gán lại giá trị

Một con trỏ có thể được gán lại. Thuộc tính này hữu ích cho việc triển khai các cấu trúc dữ liệu như danh sách liên kết, cây, v.v. Xem ví dụ sau:

int a = 5;
int b = 6;
int *p;
p =  &a;
p = &b;

Trong khi đó, tham chiếu không gán lại mà phải được gán ngay lúc khởi tạo.

int a = 5;
int b = 6;
int &p = a;
int &p = b;   //Tại dòng này sẽ hiện lỗi là "không được khai báo nhiều lần"
//Tuy nhiên, lệnh như dưới đây thì ok.
int &q=p;

3. Địa chỉ bộ nhớ

Một con trỏ có địa chỉ bộ nhớ và kích thước riêng của nó trên ngăn xếp trong khi một tham chiếu chia sẻ cùng địa chỉ bộ nhớ (với biến gốc) nhưng cũng chiếm một số không gian trên ngăn xếp.

   int &p = a;
   cout << &p << endl << &a; // Địa chỉ của p và a là như nhau

4. Giá trị NULL

Con trỏ có thể được gán NULL trực tiếp, trong khi tham chiếu không thể. Các ràng buộc liên quan đến tham chiếu (không NULL, không gán lại) đảm bảo rằng các hoạt động cơ bản không rơi vào trường hợp ngoại lệ.

5. Con trỏ đến con trỏ

Bạn có thể có các con trỏ đến con trỏ cung cấp nhiều cấp độ chuyển hướng bổ sung. Trong khi đó, các tham chiếu chỉ cung cấp một mức chuyển hướng.

//Con trỏ,
int a = 10;
int *p;
int **q;  //Con trỏ đến con trỏ.
p = &a;
q = &p;
//Đối với tham chiếu,
int &p = a;
int &&q = p; //Lỗi, không có tham chiếu của tham chiếu.

6. Các phép tính toán học

Các phép toán số học khác nhau có thể được thực hiện trên con trỏ trong khi không có thứ gọi là Số học tham chiếu. (Nhưng bạn có thể lấy địa chỉ của một đối tượng được trỏ bởi một tham chiếu và thực hiện số học con trỏ trên đó như &obj + 5)

Khi nào sử dụng cái nào

Hiệu suất hoàn toàn giống nhau, vì các tham chiếu được triển khai bên trong dưới dạng con trỏ. Tuy nhiên, bạn vẫn có thể ghi nhớ một số điểm để quyết định khi nào sử dụng cái gì:

  • Sử dụng tham chiếu:
    • Trong các tham số hàm và kiểu trả về.
  • Sử dụng con trỏ:
    • Sử dụng con trỏ nếu cấn tính toán con trỏ số học hoặc NULL. Ví dụ đối với mảng (Lưu ý rằng truy cập mảng được thực hiện bằng cách sử dụng số học con trỏ).
    • Để triển khai các cấu trúc dữ liệu như danh sách liên kết, cây, v.v. và các thuật toán của chúng vì để trỏ ô khác nhau, chúng ta phải sử dụng khái niệm con trỏ.

Ghi nhớ

Sử dụng tham chiếu khi bạn có thể và con trỏ khi bắt buộc phải. Tham chiếu thường được ưu tiên hơn con trỏ bất cứ khi nào không cần “trả về”. Điều này thường có nghĩa là các tham chiếu hữu ích nhất trong interface công khai của lớp. Các tham chiếu thường xuất hiện bên ngoài của một đối tượng và con trỏ ở bên trong.

Ngoại lệ là khi tham số hoặc giá trị trả về của một hàm cần tham chiếu “sentinel” – tham chiếu không tham chiếu đến một đối tượng. Điều này thường được thực hiện tốt nhất bằng cách trả về / lấy một con trỏ và đặt cho con trỏ NULL(các tham chiếu phải luôn là các đối tượng bí danh, không phải là một con trỏ null)


Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *