1. Vấn đề nó giải quyết
Với const int source = 1;, vì sao auto value = source; tạo ra một int có thể sửa? auto suy luận kiểu từ giá trị khởi tạo; dấu & và const trong khai báo quyết định biến mới là giá trị riêng hay tham chiếu.
2. Kiến thức cần có
Biết khai báo biến,
const, con trỏ và tham chiếuT&.Phân biệt tạo một biến mới với đặt tên khác cho đối tượng đang có.
3. Ý tưởng cốt lõi
auto dùng quy tắc suy luận tương tự tham số template. Với auto value = source, biến mới không giữ tham chiếu hay const/volatile ở mức ngoài cùng của nguồn. Với auto& view = source, tham chiếu giữ tính const của đối tượng được tham chiếu.
const ở bên trong kiểu con trỏ vẫn được giữ: sao chép một const int* bằng auto vẫn cho const int*. Quy tắc này không cho phép sửa một const int qua con trỏ mới.
4. Cú pháp tối thiểu
const int source = 1;
auto value = source;
auto& view = source;
const auto& read_only = value;value là int, còn view và read_only đều là const int&. value = 2 hợp lệ và không đổi source.
5. Cách nó hoạt động
Đọc cả dạng khai báo:
auto,auto&,const auto&hayauto&&.Với dạng giá trị
auto, mảng và hàm thường suy luận thành con trỏ. Dạng tham chiếu có thể giữ kiểu mảng/hàm.Với
auto&& r = expression, một lvalue như biếnint xchoint&; biểu thức tạm như42choint&&. Đây là hệ quả của suy luận và quy tắc gộp tham chiếu.Kiểm tra riêng dấu ngoặc nhọn: trong C++20,
auto one{1}làint, cònauto list = {1}làstd::initializer_list<int>và cần<initializer_list>.auto bad{1, 2}không hợp lệ;auto mixed = {1, 2.0}cũng không suy luận được kiểu phần tử chung.
6. Lỗi thường gặp
Cho rằng
autoluôn giữ nguyên kiểu của biến nguồn.Cho rằng
autobỏ mọiconst, kể cảconstcủa đối tượng mà con trỏ trỏ tới.Dùng
autotrong vòng lặp khi định sửa phần tử gốc; thường cầnauto&.Cho rằng tham chiếu tự kéo dài mọi vòng đời đối tượng (lifetime). Một tham chiếu tới đối tượng đã bị hủy vẫn không dùng được.
7. Khi nào nên dùng
Dùng auto khi biểu thức khởi tạo đã làm rõ kiểu hoặc kiểu rất dài, như iterator. Chọn auto& để sửa phần tử gốc, const auto& để đọc mà tránh sao chép. Viết kiểu cụ thể khi bạn cần chuyển đổi sang một kiểu đã định.
8. Ví dụ đơn giản
Đoạn kiểm tra trong mã mẫu C++20 xác nhận hai kiểu ngay lúc biên dịch:
const int source = 1;
auto value = source;
const auto& view = source;
static_assert(std::is_same_v<decltype(value), int>);
static_assert(std::is_same_v<decltype(view), const int&>);std::is_same_v cần <type_traits>. Chương trình không in gì; biên dịch thành công nghĩa là hai điều kiện đều đúng.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
dailycppinterview/001_auto-type-deduction/main.cpp
// Real-World C++ Interviews Q001: Explain auto type deduction!
// Key: `auto` follows template-style deduction: top-level references and cv-qualifiers may be
// dropped according to the declaration form, while braced initializers have special
// `std::initializer_list` rules. Write `auto&`, `const auto&`, or `auto&&` when reference
// behavior is part of the contract.
#include <type_traits>
int main() {
const int source = 1;
auto value = source;
const auto& view = source;
static_assert(std::is_same_v<decltype(value), int>);
static_assert(std::is_same_v<decltype(view), const int&>);
}
9. Điều cần nhớ
auto suy luận một kiểu tĩnh lúc biên dịch. Quyết định quan trọng là bạn cần một giá trị riêng hay một tham chiếu, rồi kiểm tra const và kiểu khởi tạo tương ứng.
10. Câu hỏi tự kiểm tra
Đề đầy đủ: Giải thích cách auto suy luận kiểu!
Với const int x = 7;, hãy xác định kiểu của auto a = x, auto& b = x và auto&& c = x. Biến nào có thể sửa trực tiếp? Vì sao auto d{7} khác auto e = {7}?