Menu
CoddyTech

Con trỏ và tham chiếu

Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 13 trên 104.

Bây giờ bạn đã hiểu về bộ nhớ stack và heap, hãy cùng khám phá các công cụ giúp bạn làm việc trực tiếp với các vị trí bộ nhớ: con trỏ và tham chiếu.

Con trỏ lưu địa chỉ bộ nhớ của một biến khác. Bạn khai báo con trỏ bằng * và lấy địa chỉ bằng &.

int value = 42;
int* ptr = &value;    // ptr lưu địa chỉ của value

std::cout << ptr;     // In ra (print) địa chỉ bộ nhớ
std::cout << *ptr;    // Giải tham chiếu: in ra 42

Tham chiếu là bí danh của một biến đã tồn tại. Sau khi được gán, nó luôn tham chiếu đến biến đó. Bạn khai báo tham chiếu bằng &.

int value = 42;
int& ref = value;     // ref là bí danh của value

ref = 100;            // Đổi value thành 100
std::cout << value;   // In ra 100

Điểm khác biệt chính:

Con trỏTham chiếu
Có thể là nullPhải được khởi tạo
Có thể được gán lạiKhông thể được liên kết lại
Dùng * để truy cập giá trịTruy cập trực tiếp giá trị
Có thể không trỏ đến đâuLuôn hợp lệ

Cả hai đều rất cần thiết để truyền đối tượng vào hàm một cách hiệu quả mà không cần sao chép, cũng như để làm việc với bộ nhớ được cấp phát trên heap. Tham chiếu an toàn và đơn giản hơn, còn con trỏ linh hoạt hơn khi bạn cần gán lại hoặc kiểm tra giá trị null.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống thao tác giá trị đơn giản để minh họa cách con trỏ và tham chiếu hoạt động khác nhau khi sửa đổi dữ liệu.

Bạn sẽ tạo hai tệp để sắp xếp code:

  • ValueOps.h: Định nghĩa ba hàm sửa đổi giá trị số nguyên theo những cách khác nhau:
    • doubleByPointer(int* ptr): nhận một con trỏ và nhân đôi giá trị mà con trỏ trỏ đến
    • tripleByReference(int& ref): nhận một tham chiếu và nhân ba giá trị
    • swapValues(int* a, int* b): nhận hai con trỏ và hoán đổi các giá trị mà chúng trỏ đến
  • main.cpp: Đọc hai số nguyên từ đầu vào, sau đó minh họa cả con trỏ và tham chiếu:
    • In ra các giá trị ban đầu: "Original: <first> <second>"
    • Dùng doubleByPointer với giá trị thứ nhất, sau đó in ra: "After double: <first>"
    • Dùng tripleByReference với giá trị thứ hai, sau đó in ra: "After triple: <second>"
    • Dùng swapValues để hoán đổi hai giá trị, sau đó in ra: "After swap: <first> <second>"

Khi gọi hàm với con trỏ, hãy nhớ dùng toán tử lấy địa chỉ (&) để truyền địa chỉ của biến. Tham chiếu hoạt động tự nhiên hơn, bạn chỉ cần truyền trực tiếp biến.

Đưa tệp tiêu đề vào main.cpp bằng #include "ValueOps.h".

Tự làm thử

#include <iostream>
#include "ValueOps.h"
using namespace std;

int main() {
    // Đọc hai số nguyên từ đầu vào
    int first, second;
    cin >> first;
    cin >> second;
    
    // In ra các giá trị ban đầu
    cout << "Original: " << first << " " << second << endl;
    
    // TODO: Dùng doubleByPointer cho giá trị thứ nhất (truyền địa chỉ bằng &)
    
    // TODO: In ra các giá trị sau khi nhân đôi
    
    // TODO: Dùng tripleByReference cho giá trị thứ hai (truyền trực tiếp biến)
    
    // TODO: In ra các giá trị sau khi nhân ba
    
    // TODO: Dùng swapValues để hoán đổi hai giá trị (truyền địa chỉ bằng &)
    
    // TODO: In ra các giá trị sau khi hoán đổi
    
    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C++ online