Bỏ qua để đến nội dung

auto không tự giữ lại reference/const

Bài “auto và suy luận kiểu dữ liệu” đã đề cập ngắn gọn: auto mặc định bỏ qua const và tham chiếu (&) của giá trị ban đầu. Đây là cạm bẫy phổ biến, đặc biệt khi dùng auto với range-based for trên container lớn.

Cạm bẫy: auto trong range-based for tạo ra bản sao không mong muốn

Phần tiêu đề “Cạm bẫy: auto trong range-based for tạo ra bản sao không mong muốn”
#include <vector>
#include <string>
#include <iostream>
int main() {
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
for (auto name : names) { // auto suy luận là std::string - TẠO BẢN SAO cho mỗi phần tử!
name += "!"; // Chỉ sửa đổi BẢN SAO, không ảnh hưởng đến names gốc
}
for (const auto& name : names) { // In ra names gốc - vẫn KHÔNG có dấu "!"
std::cout << name << " ";
}
// Alice Bob Charlie (không đổi)
return 0;
}

Với container chứa dữ liệu lớn (chuỗi dài, struct lớn), việc vô tình sao chép từng phần tử trong vòng lặp gây lãng phí hiệu năng đáng kể mà không hề có cảnh báo nào.

Giải pháp: chỉ định rõ &/const& khi cần

Phần tiêu đề “Giải pháp: chỉ định rõ &/const& khi cần”
#include <vector>
#include <string>
#include <iostream>
int main() {
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
// Chỉ đọc, không sao chép - hiệu quả nhất khi không cần sửa đổi
for (const auto& name : names) {
std::cout << name << " ";
}
// Cần sửa đổi trực tiếp phần tử trong container
for (auto& name : names) {
name += "!";
}
for (const auto& name : names) {
std::cout << name << " ";
}
// Alice! Bob! Charlie!
return 0;
}
Cú pháp Khi nào dùng
auto x = value Cần một bản sao độc lập, không quan tâm dữ liệu gốc
auto& x = value Cần sửa đổi trực tiếp giá trị gốc
const auto& x = value Chỉ cần đọc, muốn tránh sao chép dữ liệu lớn (lựa chọn mặc định tốt nhất cho range-based for)

Ví dụ khác: auto với hàm trả về tham chiếu

Phần tiêu đề “Ví dụ khác: auto với hàm trả về tham chiếu”
#include <vector>
std::vector<int> numbers = {1, 2, 3};
int& get_first() {
return numbers[0];
}
auto x = get_first(); // x là int (BẢN SAO), không phải int&!
auto& y = get_first(); // y là int& - tham chiếu THỰC SỰ đến numbers[0]
y = 100; // Sửa đổi trực tiếp numbers[0]
// x = 100; // Chỉ sửa bản sao độc lập, KHÔNG ảnh hưởng đến numbers

auto mặc định suy luận kiểu giá trị (bỏ qua const&) - dùng auto&/const auto& khi cần giữ lại tham chiếu.

  • Trong range-based for, const auto& là lựa chọn an toàn và hiệu quả nhất khi chỉ cần đọc dữ liệu
  • auto& khi cần sửa đổi trực tiếp phần tử trong container