Các câu trả lời khác đang đề cập đến những hạn chế như "bạn không thực sự biết loại biến là gì". Tôi muốn nói rằng điều này phần lớn liên quan đến quy ước đặt tên cẩu thả trong mã. Nếu giao diện của bạn được đặt tên rõ ràng, bạn không cần quan tâm loại chính xác là gì. Chắc chắn, auto result = callSomeFunction(a, b);
không nói với bạn nhiều. Nhưng auto valid = isValid(xmlFile, schema);
cho bạn biết đủ để sử dụng valid
mà không cần phải quan tâm loại chính xác của nó là gì. Rốt cuộc, chỉ với if (callSomeFunction(a, b))
, bạn cũng sẽ không biết loại này. Tương tự với bất kỳ đối tượng tạm thời phụ khác. Vì vậy, tôi không coi đây là một nhược điểm thực sự auto
.
Tôi muốn nói rằng nhược điểm chính của nó là đôi khi, kiểu trả về chính xác không phải là thứ bạn muốn làm việc. Trong thực tế, đôi khi loại trả về thực tế khác với loại trả về "logic" như một chi tiết thực hiện / tối ưu hóa. Mẫu biểu thức là một ví dụ điển hình. Hãy nói rằng chúng ta có điều này:
SomeType operator* (const Matrix &lhs, const Vector &rhs);
Logic, chúng tôi mong chờ SomeType
được Vector
, và chúng tôi chắc chắn muốn đối xử với nó như vậy trong mã của chúng tôi. Tuy nhiên, có thể vì mục đích tối ưu hóa, thư viện đại số chúng tôi đang sử dụng các mẫu biểu thức và loại trả về thực tế là:
MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);
Bây giờ, vấn đề là MultExpression<Matrix, Vector>
trong tất cả khả năng sẽ lưu trữ một const Matrix&
và const Vector&
nội bộ; nó hy vọng rằng nó sẽ chuyển đổi thành Vector
trước khi kết thúc biểu thức đầy đủ của nó. Nếu chúng ta có mã này, tất cả đều tốt:
extern Matrix a, b, c;
extern Vector v;
void compute()
{
Vector res = a * (b * (c * v));
// do something with res
}
Tuy nhiên, nếu chúng tôi đã sử dụng auto
ở đây, chúng tôi có thể gặp rắc rối:
void compute()
{
auto res = a * (b * (c * v));
// Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}