Có lý do gì để sử dụng từ khóa 'auto' trong C ++ 03 không?


85

Lưu ý rằng câu hỏi này ban đầu được đăng vào năm 2009, trước khi C ++ 11 được phê chuẩn và trước khi ý nghĩa của autotừ khóa bị thay đổi đáng kể. Các câu trả lời được cung cấp chỉ liên quan đến ý nghĩa C ++ 03 của auto- đó là một lớp lưu trữ được chỉ định - chứ không phải ý nghĩa của C ++ 11 auto- đó là loại trừ tự động. Nếu bạn đang tìm kiếm lời khuyên về thời điểm sử dụng C ++ 11 auto, câu hỏi này không liên quan đến câu hỏi đó.

Trong thời gian dài nhất, tôi nghĩ rằng không có lý do gì để sử dụng statictừ khóa trong C, bởi vì các biến được khai báo bên ngoài phạm vi khối hoàn toàn là toàn cục. Sau đó, tôi phát hiện ra rằng việc khai báo một biến như statictrong phạm vi khối sẽ cung cấp cho nó thời hạn vĩnh viễn và khai báo nó bên ngoài phạm vi khối (trong phạm vi chương trình) sẽ cung cấp cho nó phạm vi tệp (chỉ có thể được truy cập trong đơn vị biên dịch đó).

Vì vậy, điều này khiến tôi chỉ có một từ khóa mà tôi (có thể) chưa hiểu hết: autoTừ khóa. Có một số ý nghĩa khác với nó ngoài 'biến cục bộ không?' Bất cứ điều gì nó không hoàn toàn được thực hiện cho bạn ở bất cứ nơi nào bạn có thể muốn sử dụng nó? Làm thế nào để một autobiến hoạt động trong phạm vi chương trình? Gì của một static autobiến trong file-phạm vi? Từ khóa này có bất kỳ mục đích nào khác ngoài mục đích tồn tại cho sự hoàn chỉnh ?

Câu trả lời:


74

autolà một chỉ định lớp lưu trữ static, registerexterncũng vậy. Bạn chỉ có thể sử dụng một trong bốn điều này trong một khai báo.

Các biến cục bộ (không có static) có thời lượng lưu trữ tự động, có nghĩa là chúng tồn tại từ khi bắt đầu định nghĩa cho đến khi kết thúc khối của chúng. Đặt tự động trước mặt họ là thừa vì dù sao đó cũng là mặc định.

Tôi không biết lý do gì để sử dụng nó trong C ++. Trong các phiên bản C cũ có quy tắc int ngầm định, bạn có thể sử dụng nó để khai báo một biến, như trong:

int main(void) { auto i = 1; }

Để làm cho nó hợp lệ cú pháp hoặc phân biệt khỏi một biểu thức gán trong trường hợp ilà trong phạm vi. Nhưng điều này không hoạt động trong C ++ (bạn phải chỉ định một loại). Thật buồn cười, Tiêu chuẩn C ++ viết:

Một đối tượng được khai báo mà không có bộ chỉ định lớp lưu trữ ở phạm vi khối hoặc được khai báo dưới dạng tham số hàm có thời lượng lưu trữ tự động theo mặc định. [Lưu ý: do đó, bộ chỉ định tự động hầu như luôn thừa và không thường xuyên được sử dụng; một công dụng của auto là phân biệt rõ ràng một câu lệnh khai báo với một câu lệnh biểu thức (6.8). - ghi chú cuối]

mà đề cập đến kịch bản sau, có thể là một tập hợp của ađến inthoặc khai báo một biến akiểu intcó dấu ngoặc đơn thừa xung quanh a. Nó luôn được coi là một tuyên bố, vì vậy autosẽ không thêm bất cứ điều gì hữu ích ở đây, mà thay vào đó sẽ cho con người. Nhưng một lần nữa, con người sẽ tốt hơn nếu loại bỏ các dấu ngoặc đơn thừa xung quanh a, tôi sẽ nói:

int(a);

Với ý nghĩa mới autokhi đến với C ++ 0x, tôi sẽ không khuyến khích sử dụng nó với ý nghĩa của C ++ 03 trong mã.


4
C ++ biên dịch thường được sử dụng để có implicit int cho các giá trị trở về từ chức năng, trở lại trong những ngày ARM trước khi tiêu chuẩn ... Trước khi EMPIRE ...
Daniel Earwicker

1
Tôi chỉ nhận ra nó là cách trình biên dịch của tôi cho tôi biết rằng tôi đã quên khai báo chuyển tiếp một hàm. Nó sẽ cho tôi biết rằng cách sử dụng một hàm của tôi khác với cách nó được khai báo vì hàm int ngầm định.
Carson Myers

29
Phần tốt nhất là các lập trình viên đã từng viết "auto" (bốn chữ cái) để tránh viết "int" (ba chữ cái).
Max Lybbert

30
@Max - này, rất nhiều người nói "double-u-double-u-double-u" là từ viết tắt của "World Wide Web".
Daniel Earwicker

3
@smichak không, "dễ bay hơi" là một định tính loại. Thay vì xác định nơi lưu trữ một giá trị, nó thay đổi hành vi ghi và đọc từ một đối tượng thuộc loại đủ điều kiện dễ bay hơi. Có thể có các biến ngăn xếp đủ điều kiện dễ bay hơi (lớp lưu trữ tự động) cũng như các biến thời lượng lưu trữ tĩnh đủ điều kiện dễ bay hơi (lớp lưu trữ 'tĩnh' cục bộ, các biến không cục bộ). Bên cạnh đó, tôi không biết liệu "đăng ký biến động" có phải là một kết hợp hợp lệ hay không :)
Johannes Schaub - litb

86

Trong C ++ 11, autocó một ý nghĩa mới: nó cho phép bạn tự động suy ra kiểu của một biến.

Tại sao điều đó lại hữu ích? Hãy xem xét một ví dụ cơ bản:

std::list<int> a;
// fill in a
for (auto it = a.begin(); it != a.end(); ++it) {
  // Do stuff here
}

autođó tạo ra một trình lặp kiểu std::list<int>::iterator.

Điều này có thể làm cho một số mã phức tạp nghiêm trọng dễ đọc hơn nhiều.

Một vi dụ khac:

int x, y;
auto f = [&]{ x += y; };
f();
f();

Ở đó, autosuy ra kiểu cần thiết để lưu biểu thức lambda trong một biến. Wikipedia có phạm vi bảo hiểm tốt về chủ đề này.


4
Vẫn không chắc đây có phải là cách sử dụng tự động tuyệt vời hay không. Mã phải dễ đọc, không dễ viết!
DanDan

38
Tôi không biết về bạn nhưng tôi thấy điều này dễ đọc hơn nhiều so với spam kiểu trình lặp.
Vượt qua

17
Và nếu bạn quyết định thay đổi lớp từ danh sách <int> sang một lớp khác, bạn không cần phải tìm kiếm mọi khai báo của trình lặp và thay đổi nó.
roslav

2
@KarateSnowMachine: Nếu bạn muốn const, bạn sẽ sử dụng "const auto" thay vì "auto".
darth

4
@darth const auto it = a.begin();sẽ cung cấp cho bạn một const iterator, không phải a const_iterator. Bạn vẫn nên thay đổi phần tử, nhưng ++itsẽ không biên dịch được. Để có được một const_iterator, bạn sẽ sử dụngauto it = a.cbegin();
fredoverflow 14/12/13

35

Từ khóa tự động không có mục đích vào lúc này. Bạn chính xác là nó chỉ định lại lớp lưu trữ mặc định của một biến cục bộ, một giải pháp thay thế thực sự hữu ích static.

Nó có một ý nghĩa hoàn toàn mới trong C ++ 0x. Điều đó cho bạn một số ý tưởng về việc nó vô dụng như thế nào!


1
Ôi trời, điều đó có bao giờ vô ích không. Tôi thích ý nghĩa mới. Nó làm cho một số mã ít dài dòng và thừa hơn rất nhiều.
Carson Myers

Vâng, đã sử dụng từ tương đương trong C #, nó có thể sẽ tạo ra sự khác biệt rất lớn. Hơn thế nữa trong C ++ nếu bạn đang sử dụng các mẫu biểu thức trong đó các kiểu phức tạp đến mức chúng không bao giờ được dự định viết ra bằng tay.
Daniel Earwicker

7

GCC có công dụng đặc biệt autodành cho các hàm lồng nhau - xem tại đây .

Nếu bạn có hàm lồng nhau mà bạn muốn gọi trước định nghĩa của nó, bạn cần khai báo hàm đó với auto.


đây là một triển khai tự động tuyệt vời, mặc dù phụ thuộc vào trình biên dịch. Cảm ơn các nghiên cứu :)
Carson Myers

3

"auto" được cho là nói với trình biên dịch để tự quyết định nơi đặt biến (bộ nhớ hoặc thanh ghi). Tương tự của nó là "đăng ký", được cho là yêu cầu trình biên dịch cố gắng giữ nó trong một thanh ghi. Các trình biên dịch hiện đại bỏ qua cả hai, vì vậy bạn cũng nên làm như vậy.


1
Không chính xác - nếu bạn khai báo nó bằng "register", các trình biên dịch sẽ không cho phép bạn sử dụng toán tử address-of (& foo) trên biến bởi vì, nó không tồn tại ở bất kỳ đâu trong bộ nhớ (và do đó không có địa chỉ).
Tim Čas

3

Tôi sử dụng từ khóa này để ghi rõ ràng khi nó là quan trọng đối với hàm, rằng biến được đặt trên ngăn xếp, đối với bộ xử lý dựa trên ngăn xếp. Chức năng này có thể được yêu cầu khi sửa đổi ngăn xếp trước khi trả về từ một chức năng (hoặc quy trình dịch vụ ngắt). Trong trường hợp này, tôi tuyên bố:

auto unsigned int auiStack[1];   //variable must be on stack

Và sau đó tôi truy cập bên ngoài biến:

#define OFFSET_TO_RETURN_ADDRESS 8     //depends on compiler operation and current automatics
auiStack[OFFSET_TO_RETURN_ADDRESS] = alternate_return_address;

Vì vậy, autotừ khóa giúp ghi lại ý định.


Tôi cho rằng đây chỉ là ý định báo hiệu, vì từ khóa không thực sự thực thi vị trí ngăn xếp, hơn là đơn giản bỏ qua nó sẽ làm được.
underscore_d

2

Theo Stroustrup, trong "Ngôn ngữ lập trình C" (Phiên bản thứ 4, bao gồm C 11), việc sử dụng 'tự động' có những lý do chính sau (phần 2.2.2) (Các từ Stroustrup được trích dẫn):

1)

Định nghĩa này nằm trong một phạm vi rộng lớn mà chúng tôi muốn làm cho loại mã này hiển thị rõ ràng cho người đọc mã của chúng tôi.

Với 'auto' và bộ khởi tạo cần thiết của nó, chúng ta có thể biết loại của biến trong nháy mắt!

2)

Chúng tôi muốn nói rõ về phạm vi hoặc độ chính xác của biến (ví dụ: double thay vì float)

Theo tôi một trường hợp phù hợp ở đây, là một cái gì đó như thế này:

   double square(double d)
    {
        return d*d; 
    }

    int square(int d)
    {
        return d*d; 
    }

    auto a1 = square(3);

    cout << a1 << endl;

    a1 = square(3.3);

    cout << a1 << endl;

3)

Sử dụng 'tự động', chúng tôi tránh dư thừa và viết tên kiểu dài.

Hãy tưởng tượng một số tên kiểu dài từ một trình lặp được tạo mẫu:

(mã từ phần 6.3.6.1)

template<class T> void f1(vector<T>& arg) {
    for (typename vector<T>::iterator p = arg.begin(); p != arg.end();   p)
        *p = 7;

    for (auto p = arg.begin(); p != arg.end();   p)
        *p = 7;
}

1

Trong trình biên dịch cũ, auto là một cách để khai báo một biến cục bộ. Bạn không thể khai báo các biến cục bộ trong các trình biên dịch cũ như Turbo C mà không có từ khóa auto hoặc một số biến như vậy.


1

Ý nghĩa mới của từ khóa auto trong C ++ 0x được Stephan T. Lavavej của Microsoft mô tả rất độc đáo trong một video bài giảng có thể xem / tải xuống miễn phí trên STL được tìm thấy tại trang MSDN's Channel 9 tại đây .

Toàn bộ bài giảng rất đáng xem, nhưng phần về từ khóa tự động nằm ở phút thứ 29 (ước chừng).


0

Có một số ý nghĩa khác đối với 'tự động' ngoài 'biến cục bộ không?'

Không có trong C ++ 03.

Bất cứ điều gì nó không hoàn toàn được thực hiện cho bạn bất cứ nơi nào bạn có thể muốn sử dụng nó?

Không có gì cả, trong C ++ 03.

Làm thế nào để một biến tự động hoạt động trong phạm vi chương trình? Biến tự động tĩnh trong phạm vi tệp là gì?

Từ khóa không được phép bên ngoài nội dung hàm / phương pháp.

Từ khóa này có bất kỳ mục đích nào [trong C ++ 03] ngoài mục đích tồn tại để hoàn thiện không?

Đáng ngạc nhiên là có. Tiêu chí thiết kế của C ++ bao gồm mức độ tương thích ngược cao với C. C có từ khóa này và không có lý do thực sự nào để cấm nó hoặc xác định lại ý nghĩa của nó trong C ++. Vì vậy, mục đích ít tương thích hơn với C.

Từ khóa này có bất kỳ mục đích nào trong C ngoài mục đích tồn tại cho sự hoàn chỉnh không?

Tôi mới biết được một điều gần đây: sự dễ dàng chuyển các chương trình cổ từ B. C phát triển từ một ngôn ngữ tên B có cú pháp khá giống với ngôn ngữ C. Tuy nhiên, B không có kiểu nào cả. Cách duy nhất để khai báo một biến trong B là chỉ định kiểu lưu trữ của nó ( autohoặc extern). Như thế này:

tự động tôi;

Cú pháp này vẫn hoạt động trong C và tương đương với

int i;

bởi vì trong C, lớp lưu trữ được mặc định thành autovà kiểu được mặc định thành int. Tôi đoán rằng mọi chương trình bắt nguồn từ B và được chuyển sang C đều chứa đầy các autobiến vào thời điểm đó.

C ++ 03 không còn cho phép kiểu int ngầm định của C, nhưng nó vẫn giữ nguyên autotừ khóa không còn hữu dụng chính xác nữa vì không giống như int tường minh, nó không gây ra bất kỳ rắc rối nào trong cú pháp của C.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.