Kiểu Trả Về Và Câu Lệnh Trả Về Trong C++

Cơ chế trả về của hàm trong C++

  • Câu lệnh return đóng vai trò kết thúc việc thực thi hàm và trả quyền kiểm soát cho điểm gọi hàm
  • Có hai dạng cơ bản của câu lệnh return:
  • return; (dùng cho hàm không có giá trị trả về)
  • return biểu_thức; (trả về giá trị cụ thể)
  • Hàm không phải void bắt buộc phải trả về giá trị có kiểu phù hợp với khai báo, vi phạm sẽ gây lỗi biên dịch

Kiểu dữ liệu trả về của hàm

  • Kiểu dữ liệu trả về xác định tính chất của biểu thức gọi hàm:
  • Hàm trả về tham chiếu sẽ tạo ra giá trị trái (lvalue)
  • Các kiểu trả về khác tạo ra giá trị phải (rvalue)
  • Biểu thức gọi hàm trả về tham chiếu có thể được gán giá trị mới:
  • Cho phép thay đổi đối tượng gốc nếu hàm trả về tham chiếu không phải const
  • Để tránh thay đổi không mong muốn, nên khai báo hàm trả về const

Cơ chế truyền giá trị trả về

  • Mặc định, giá trị trả về được truyền bằng cách sao chép
  • Quy trình này tương tự như khởi tạo biến hoặc tham số hình thức
  • Giá trị trả về được dùng để khởi tạo một đối tượng tạm thời tại điểm gọi hàm

Trả về tham chiếu

  • Hàm được khai báo trả về tham chiếu sẽ không sao chép đối tượng mà trực tiếp trỏ đến đối tượng gốc
  • Tham chiếu trả về chỉ là tên gọi khác của đối tượng
// Tìm chuỗi có độ dài ngắn hơn giữa hai chuỗi đầu vào
const string& findShorterString(const string& s1, const string& s2)
{
    return (s1.size() <= s2.size()) ? s1 : s2;
}
// Hàm không sao chép đối tượng mà chỉ trỏ trực tiếp đến s1 hoặc s2

Lưu ý quan trọng:

  • Không nên trả về tham chiếu hoặc con trỏ đến đối tượng cục bộ:
  • Khi hàm kết thúc, vùng nhớ stack chứa đối tượng cục bộ sẽ bị giải phóng
  • Truy cập đến các tham chiếu/trỏ đã trả về sẽ dẫn đến truy cập vùng nhớ không hợp lệ
const string& getLocalReference()
{
    string temp;      // Đối tượng cục bộ
    // ... xử lý temp
    if (!temp.empty())
        return temp;  // LỖI: Trả về tham chiếu đến đối tượng cục bộ
    else
        return "Empty"; // LỖI: Trả về tham chiếu đến đối tượng tạm thời
}

Trả về danh sách giá trị (C++11)

  • Từ C++11, hàm có thể trả về danh sách giá trị trong ngoặc nhọn
  • Danh sách rỗng sẽ khởi tạo giá trị mặc định, ngược lại:
  • Với kiểu nguyên thủy: danh sách chỉ chứa tối đa 1 giá trị
  • Với kiểu lớp: quy tắc khởi tạo do lớp định nghĩa
vector<string> processRequest()
{
    if (checkCondition())
        return {};          // Trả về vector rỗng
    else
        return {"Success", "Data1", "Data2"}; // Trả về vector có 3 phần tử
}

Giá trị trả về của hàm main

  • Hàm main luôn có kiểu trả về là int (0 = thành công, khác 0 = thất bại)
  • Có thể không có câu lệnh return (compiler tự động thêm return 0;)
  • Các hằng số EXIT_SUCCESSEXIT_FAILURE được định nghĩa trong thư viện chuẩn

Cú pháp trả về đuôi (trailing return type)

Dùng hiệu quả cho các kiểu trả về phức tạp:

auto calculateFactorial(int n) -> int;
auto findShorter(string& s1, string& s2) -> string&;
// Hàm trả về con trỏ đến mảng 10 phần tử kiểu int
int (*processData(int i))[10];
// Sử dụng cú pháp đuôi để tăng tính đọc hiểu
auto processData(int i) -> int(*)[10];

Thẻ: C++ return-type reference function trailing-return

Đăng vào ngày 18 tháng 5 lúc 03:59