Để trình biên dịch chọn kiểu
Ở trang trước, bạn đã thấy mọi biến C++ đều có một kiểu cố định: int, double, std::string, v.v. Tự tay ghi kiểu thì ổn với int count = 0;, nhưng sẽ rườm rà khi tên kiểu dài ra. Từ khóa (keyword) auto (từ C++11 trở đi) cho phép trình biên dịch suy ra kiểu từ giá trị bạn gán, nên bạn chỉ cần viết giá trị một lần và để trình biên dịch lo phần còn lại.
Ý chính: auto không phải kiểu động. Mỗi biến vẫn có đúng một kiểu cụ thể, được chốt lúc biên dịch. auto chỉ giúp bạn khỏi phải ghi kiểu ra.
Vì sao auto đáng dùng
Với những kiểu ngắn và hiển nhiên, auto count = 0; và int count = 0; dễ đọc như nhau. auto thật sự phát huy tác dụng với những tên kiểu dài và lặp đi lặp lại, loại bạn gặp ở các container và iterator của thư viện chuẩn.
So sánh phiên bản dài dòng với phiên bản dùng auto:
// Without auto - the type is written twice, in effect
std::vector<std::pair<std::string, int>>::iterator it = scores.begin();
// With auto - the compiler already knows the type
auto it = scores.begin();
Cả hai khai báo đúng cùng một kiểu iterator. Cách thứ hai dễ đọc hơn và không bị lệch nếu sau này bạn đổi scores sang một container khác.
Đây là ví dụ trong một chương trình hoàn chỉnh:
auto trong vòng lặp for dạng range
Chỗ bạn gặp auto nhiều nhất là vòng lặp for dạng range. Gần như bạn không bao giờ muốn tự ghi kiểu phần tử, và cách bạn viết auto quyết định bạn nhận được bản sao hay tham chiếu.
Ba biến thể bạn sẽ gặp, và ý nghĩa của từng cái:
for (auto x : v):xlà bản sao của từng phần tử. Rẻ vớiint, lãng phí với đối tượng lớn.for (auto& x : v):xlà tham chiếu; bạn có thể sửa các phần tử ngay tại chỗ.for (const auto& x : v):xlà tham chiếu chỉ đọc. Dùng khi bạn chỉ cần đọc.
Chương trình tiếp theo sửa đổi container qua auto&:
Cái bẫy: viết for (auto n : nums) (không có &) trong vòng lặp đó thì n *= 10 chỉ âm thầm thay đổi bản sao, còn nums vẫn nguyên. Trình biên dịch không cảnh báo gì cả, vòng lặp chỉ đơn giản là không làm được gì có ích.
Những gì auto lược bỏ
auto thường suy ra kiểu giống như cách một tham số hàm truyền theo giá trị: nó bỏ đi const ở mức ngoài cùng, tham chiếu và volatile. Nghĩa là auto luôn cho bạn một bản sao mới, sửa được, trừ khi bạn yêu cầu khác.
Nếu muốn giữ const hoặc tránh sao chép, bạn tự thêm các từ bổ nghĩa. Khuôn mẫu là trang trí auto giống như cách bạn trang trí bất kỳ kiểu nào:
Vậy auto suy ra kiểu cơ sở; &, const và * là những nút điều chỉnh bạn thêm vào. auto là kiểu, const auto& là tham chiếu chỉ đọc tới kiểu đó.
Lỗi thường gặp và cái bẫy
auto giảm công gõ phím, chứ không giảm nhu cầu hiểu về kiểu. Vài cái bẫy hay bắt người mới:
Bắt buộc phải khởi tạo. auto không có gì để suy ra từ một khai báo trống, nên đây là lỗi biên dịch:
auto x; // error: declaration of 'auto x' has no initializer
auto y = 0; // fine
Số nguyên literal là int, không phải double. auto half = 1 / 2; suy ra int và lưu 0, vì 1 / 2 là phép chia nguyên được tính trước khi auto kịp thấy nó. Kiểu đi theo giá trị:
auto bỏ đi tham chiếu, hãy cẩn thận với những bản sao bất ngờ. Nếu một hàm trả về tham chiếu mà bạn nhận nó bằng auto thường, bạn sẽ có một bản sao, đôi khi là một bug hiệu năng thật sự trong vòng lặp chạy nhiều (sao chép sâu một đối tượng lớn ở mỗi lần lặp). Hãy dùng const auto& khi ý bạn là "chỉ xem, không lấy".
Đừng giấu kiểu khi kiểu quan trọng. auto result = compute(); ổn khi kiểu trả về của compute hiển nhiên từ ngữ cảnh, nhưng nếu người đọc phải đi tìm xem result thật ra là gì, ghi rõ kiểu có thể là lựa chọn thân thiện hơn. auto dùng để bớt rườm rà, không phải để che giấu ý định.
Tiếp theo: hằng số và const
Bạn đã thấy auto cố ý bỏ const trừ khi bạn yêu cầu giữ lại, và điều đó dẫn tới câu hỏi hiển nhiên: const thật sự đảm bảo điều gì, và khi nào bạn nên đánh dấu một giá trị là không thể thay đổi? Trang tiếp theo đi sâu vào const, biểu thức hằng, và vì sao "mặc định dùng const" là một trong những thói quen hữu ích nhất trong C++.
Câu hỏi thường gặp
Từ khóa auto trong C++ dùng để làm gì?
auto bảo trình biên dịch suy ra kiểu của biến từ giá trị khởi tạo. auto x = 5; khiến x có kiểu int; auto y = 3.14; khiến y có kiểu double. Kiểu được cố định lúc biên dịch: auto không phải kiểu động, mà chỉ là cách viết tắt thay cho việc tự ghi kiểu.
auto có giữ lại const và tham chiếu trong C++ không?
Không. auto thường bỏ đi const ở mức ngoài cùng, tham chiếu và volatile. Nếu nguồn là const int& r, thì auto x = r; cho bạn một bản sao int bình thường. Để giữ lại chúng, bạn phải ghi rõ: dùng const auto& để gắn một tham chiếu chỉ đọc mà không sao chép.
Có thể khai báo biến auto mà không khởi tạo không?
Không. auto x; là lỗi biên dịch vì không có giá trị khởi tạo nào để trình biên dịch suy ra kiểu. Mọi biến auto đều phải được gán giá trị ngay tại chỗ khai báo.