Bao nhiêu là quá nhiều với từ khóa tự động C ++ 11?


218

Tôi đã sử dụng autotừ khóa mới có sẵn trong tiêu chuẩn C ++ 11 cho các loại khuôn mẫu phức tạp, đó là những gì tôi tin rằng nó được thiết kế cho. Nhưng tôi cũng đang sử dụng nó cho những việc như:

auto foo = std::make_shared<Foo>();

Và hoài nghi hơn cho:

auto foo = bla(); // where bla() return a shared_ptr<Foo>

Tôi chưa thấy nhiều cuộc thảo luận về chủ đề này. Dường như autocó thể bị lạm dụng, vì một loại thường là một dạng tài liệu và kiểm tra độ tỉnh táo. Nơi nào bạn vẽ đường trong việc sử dụng autovà các trường hợp sử dụng được đề xuất cho tính năng mới này là gì?

Để làm rõ: Tôi không yêu cầu một ý kiến ​​triết học; Tôi đang yêu cầu mục đích sử dụng từ khóa này của ủy ban tiêu chuẩn, có thể với các nhận xét về cách sử dụng mục đích đó được thực hiện trong thực tế.

Lưu ý bên lề: Câu hỏi này đã được chuyển đến SE.Programmer và sau đó quay lại Stack Overflow. Thảo luận về điều này có thể được tìm thấy trong câu hỏi meta này .


Đây là một trang web hỏi đáp, không phải là một trang thảo luận. Bạn đã hỏi một câu hỏi rất chung chung và tôi nghi ngờ rằng bất kỳ ai cũng sẽ có thể cung cấp cho bạn bất cứ điều gì ngoài một câu hỏi rất chủ quan. (đó là lý do -1)
TravisG

15
@heishe, tôi đã thêm một sự làm rõ. Nếu bạn đọc câu hỏi rất chung chung, có vẻ như nó đang hỏi một ý kiến ​​chủ quan, nhưng thực sự nếu bạn đã sử dụng autotừ khóa, thì bạn sẽ biết nó nên được sử dụng như thế nào . Đó là những gì tôi đang hỏi, với tư cách là người mới sử dụng tính năng này, tôi nên sử dụng nó như thế nào?
Alan Turing

13
Tôi đã thấy cuộc thảo luận này ở khắp mọi nơi khi C # giới thiệu var(nghĩa là, một khi mọi người đã vượt qua ý tưởng rằng đó không phải là kiểu gõ động). Nếu bạn muốn bạn có thể bắt đầu với câu hỏi này và đi qua các câu hỏi liên quan.
R. Martinho Fernandes

2
@Lex: Hoặc một cái gì đó là hợp pháp hoặc nó không phải là; gọi một cái gì đó "xấu" là hợp pháp là chủ quan theo định nghĩa. Tức là, gọi auto foo = bla();"xấu" rõ ràng là một ý kiến, không phải là một thực tế, điều này làm cho câu hỏi này và trả lời một cuộc thảo luận, làm cho nó có liên quan đến Lập trình viên SE, đó chính xác là những gì các phiếu bầu gần chỉ ra. / nhún vai
ildjarn

3
Herb Sutter xem về vấn đề này: Herbutter.com/2013/06/13/ Từ
rafak

Câu trả lời:


131

Tôi nghĩ rằng người ta nên sử dụng autotừ khóa bất cứ khi nào thật khó để nói cách viết loại từ cái nhìn đầu tiên, nhưng loại phía bên phải của một biểu thức là rõ ràng. Ví dụ: sử dụng:

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

để có được loại khóa tổng hợp boost::multi_index, mặc dù bạn biết rằng đó là int. Bạn không thể viết intvì nó có thể được thay đổi trong tương lai. Tôi sẽ viết autotrong trường hợp này.

Vì vậy, nếu autotừ khóa cải thiện khả năng đọc trong một trường hợp cụ thể thì hãy sử dụng nó. Bạn có thể viết autokhi nó rõ ràng cho người đọc loại autođại diện.

Dưới đây là một số ví dụ:

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)

18
Đó dường như không phải là một khuyến nghị rất tốt. Bao lâu thì bạn không biết loại đối tượng? (Bên ngoài các mẫu, nghĩa là vậy.) Và nếu bạn không biết họ gõ, hãy tìm nó, đừng lười biếng và sử dụng tự động.
Paul Manta

9
@Paul: thường thì bạn chỉ biết hoặc chỉ cần biết phần quan trọng nhất của loại, ví dụ: đó là trình lặp, nhưng bạn không biết và không quan tâm đó là trình lặp của vectơ hay trình lặp của liên kết danh sách; trong những trường hợp đó, bạn thực sự không muốn dành thời gian và không gian màn hình để cố gắng tìm ra cách viết ra các loại.
Nói dối Ryan

45
Dù bhard C ++ có thích hay không, C ++ 0x sẽ thu hút những người chưa bao giờ sử dụng C ++. Và những người sẽ sử dụng tự động khắp nơi.
Giáo sư Falken

6
@ R.MartinhoFernandes - không, điều duy nhất rõ ràng là bất cứ điều gì bla() bạn trả lại cho nó foo.
Luis Machuca

8
@LuisMachuca câu trả lời của tôi là một cách nói thẳng thắn khi nói rằng thật không trung thực khi đưa ra một ví dụ trong sách giáo khoa về biến và chức năng đặt tên xấu và đổ lỗi cho sự thiếu khả năng đọc của nó về suy luận kiểu.
R. Martinho Fernandes

62

Sử dụng autoở mọi nơi mà bạn có thể đặc biệt const autođể các tác dụng phụ ít phải quan tâm hơn. Bạn sẽ không phải lo lắng về các loại ngoại trừ trong các trường hợp rõ ràng, nhưng chúng vẫn sẽ được xác minh tĩnh cho bạn và bạn có thể tránh một số sự lặp lại. Nếu autokhông khả thi, bạn có thể sử dụng decltypeđể thể hiện các loại về mặt ngữ nghĩa dưới dạng hợp đồng dựa trên biểu thức. Mã của bạn sẽ trông khác nhau, nhưng nó sẽ là một thay đổi tích cực.


12
Tôi đặc biệt nói 'const auto &'
Viktor Sehr

2
Sử dụng tốt hơn auto&&trong các tình huống phức tạp edmundv.home.xs4all.nl/blog/2014/01/11/iêu
KindDragon

2
@KindDragon: Đó là một quy tắc tốt, nhưng tôi thích sử dụng const auto&hoặc const autotrừ khi tôi rõ ràng muốn đột biến hoặc di chuyển.
Jon Purdy

" Sử dụng tự động ở mọi nơi bạn có thể ". Điều này có nghĩa là tôi nên viết auto str = std::string();thay vì std::string str;?
Calmarius

4
Sử dụng tự động ở mọi nơi sẽ làm cho mã của bạn ít đọc hơn và khó gỡ lỗi hơn vì bạn sẽ phải tự suy luận các loại trong khi đọc mã.
SubMachine

52

Dễ dàng. Sử dụng nó khi bạn không quan tâm loại đó là gì. Ví dụ

for (const auto & i : some_container) {
   ...

Tất cả những gì tôi quan tâm ở đây ilà bất cứ thứ gì trong container.

Nó hơi giống typedefs.

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

Ở đây, tôi không quan tâm liệu hwlà phao hoặc đôi, chỉ rằng họ là bất cứ loại thích hợp để diễn tả chiều cao và trọng lượng .

Hoặc xem xét

for (auto i = some_container .begin (); ...

Ở đây tất cả những gì tôi quan tâm là nó là một trình vòng lặp phù hợp, hỗ trợ operator++(), nó giống như kiểu gõ vịt trong khía cạnh này.

Ngoài ra loại lambdas không thể đánh vần, auto f = []...phong cách cũng tốt. Sự thay thế là đúc std::functionnhưng đi kèm với chi phí.

Tôi không thể thực sự quan niệm về một "lạm dụng" auto. Cách gần nhất tôi có thể tưởng tượng là tước đi một chuyển đổi rõ ràng thành một loại quan trọng - nhưng bạn sẽ không sử dụng autocho điều đó, bạn sẽ xây dựng một đối tượng của loại mong muốn.

Nếu bạn có thể loại bỏ một số dư thừa trong mã của bạn mà không cần giới thiệu tác dụng phụ, sau đó nó phải là tốt để làm như vậy.

Counterexamples (mượn từ câu trả lời của người khác):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

Ở đây chúng tôi quan tâm loại này là gì, vì vậy chúng tôi nên viết Someclass i;for(unsigned x = y;...


1
Ừm. Không dễ thế đâu. Nó biên dịch và chạy, và bạn chỉ cần tự bắn vào chân mình nếu các mục đó là các đối tượng không cần thiết-- phép lặp của bạn gọi hàm tạo sao chép và hàm hủy trong mỗi bước lặp. Nếu bạn sẽ sử dụng tự động một cách mù quáng trong trình lặp dựa trên phạm vi, thì có lẽ nên là "for (const auto & item: some_container)" thay vì "for (auto item: some_container)".
Don nở

2
Không phải luôn luôn, nhưng ok bạn có thể muốn tham khảo. Vậy thì sao? Điều đó không có gì để làm với auto.
spraff

Tôi thực sự không hiểu bình luận cuối cùng của bạn. Tôi đã cố gắng giải thích lý do tại sao chiến lược của bạn không giống với chiến lược của tôi và tại sao tôi lại hạ thấp nó.
Don nở

5
Tôi đang nói rằng việc bạn có sử dụng tài liệu tham khảo hay không là trực giao với việc bạn có sử dụng tự động hay không. Tôi sẽ chỉnh sửa nó để thêm tài liệu tham khảo vì phải thừa nhận rằng đó thường là những gì người ta muốn làm, nhưng nó hoàn toàn không liên quan đến chủ đề trong tay.
spraff

43

Cứ liều thử đi. Sử dụng autobất cứ nơi nào nó làm cho việc viết mã dễ dàng hơn.

Mỗi tính năng mới trong bất kỳ ngôn ngữ nào sẽ bị lạm dụng bởi ít nhất một số loại lập trình viên. Chỉ thông qua việc sử dụng quá mức vừa phải bởi một số lập trình viên có kinh nghiệm (không phải noobs) mà phần còn lại của các lập trình viên có kinh nghiệm tìm hiểu ranh giới của việc sử dụng đúng. Việc sử dụng quá mức thường là xấu, nhưng có thể là tốt vì việc lạm dụng như vậy có thể dẫn đến những cải tiến trong tính năng hoặc một tính năng tốt hơn để thay thế nó.

Nhưng nếu tôi đang làm việc với mã với hơn một vài dòng như

auto foo = bla();

trong đó loại được biểu thị bằng 0 lần, tôi có thể muốn thay đổi các dòng đó để bao gồm các loại. Ví dụ đầu tiên là tuyệt vời vì loại được nêu một lần và autogiúp chúng ta không phải viết các loại templated lộn xộn hai lần. Hoan hô cho C ++++. Nhưng hiển thị rõ ràng loại 0 lần, nếu nó không dễ dàng nhìn thấy trong một dòng gần đó, khiến tôi lo lắng, ít nhất là trong C ++ và những người kế nhiệm ngay lập tức. Đối với các ngôn ngữ khác được thiết kế để hoạt động ở cấp độ cao hơn với tính trừu tượng, đa hình và tính tổng quát hơn, điều đó tốt.


38

Tại C ++ và Beyond 2012 trong bảng điều khiển Ask Us Anything , đã có một cuộc trao đổi tuyệt vời giữa Andrei Alexandrescu, Scott Meyers và Herb Sutter nói về khi nào nên sử dụng và không sử dụngauto . Bỏ qua đến phút 25:03 để thảo luận 4 phút. Tất cả ba loa cho điểm tuyệt vời nên được lưu ý khi không sử dụng auto.

Tôi rất khuyến khích mọi người đi đến kết luận của riêng họ, nhưng việc tôi bỏ đi là sử dụng autoở mọi nơi trừ khi :

  1. Nó làm tổn thương khả năng đọc
  2. Có mối quan tâm về chuyển đổi loại tự động (ví dụ: từ nhà xây dựng, chuyển nhượng, loại trung gian mẫu, chuyển đổi ngầm định giữa độ rộng số nguyên)

Việc sử dụng tự do explicitgiúp giảm bớt mối quan tâm cho người sau, điều này giúp giảm thiểu lượng thời gian trước đây là một vấn đề.

Đọc lại những gì Herb nói, "nếu bạn không làm X, Y và Z, hãy sử dụng auto. Tìm hiểu X, Y và Z là gì và đi ra ngoài và sử dụng autoở mọi nơi khác."


4
Có lẽ cũng có giá trị liên kết đến "hầu như luôn luôn tự động" - Herbutter.com/2013/08/12/ từ
Rob Starling

37

Vâng, nó có thể được sử dụng quá mức gây hại cho khả năng đọc. Tôi đề nghị sử dụng nó trong các bối cảnh nơi các loại chính xác dài, hoặc không gây nhiễu, hoặc không quan trọng đối với khả năng đọc và các biến chỉ tồn tại trong thời gian ngắn. Ví dụ, loại lặp thường dài và không quan trọng, vì vậy autosẽ hoạt động:

   for(auto i = container.begin(); i != container.end(); ++i);

auto ở đây không làm tổn thương khả năng đọc.

Một ví dụ khác là loại quy tắc phân tích cú pháp, có thể dài và phức tạp. Đối chiếu:

   auto spaces = space & space & space;

với

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

Mặt khác, khi loại được biết đến và đơn giản, sẽ tốt hơn nhiều nếu nó được nêu rõ ràng:

int i = foo();

thay vì

auto i = foo();

2
Tất nhiên, việc có một vòng lặp dựa trên phạm vi trong ngôn ngữ làm cho ví dụ đầu tiên của bạn bớt thú vị hơn. 8v)
Fred Larson

@Fred: loại vẫn có thể cồng kềnh (Tôi đang nghĩ các container kết hợp)
Matthieu M.

3
@Fred: Bất cứ khi nào giới hạn của bạn không begin()end(), hoặc kích thước bước của bạn là bất kỳ thứ gì khác, hoặc bạn đang sửa đổi vùng chứa khi bạn lặp, câu lệnh dựa trên phạm vi sẽ không giúp bạn.
Dennis Zickefoose

6
@geotavros: Và r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>không?
Dennis Zickefoose

7
@geotavros: Hoặc bạn có thể xem loại nào spacevà tìm kiếm loại đó. Dù sao đó cũng là thông tin hữu ích hơn ... vấn đề không phải là "biến mới này là loại gì" mà là "có space & space & spacenghĩa là gì?" Loại thực tế của biểu thức chỉ là tiếng ồn.
Dennis Zickefoose

19

auto có thể rất nguy hiểm khi kết hợp với các mẫu biểu thức được sử dụng rất nhiều bởi các thư viện đại số tuyến tính như Eigen hoặc OpenCV.

auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.

Lỗi gây ra bởi loại sai lầm này là một nỗi đau lớn để gỡ lỗi. Một biện pháp khắc phục có thể là phân phối rõ ràng kết quả cho loại dự kiến ​​nếu bạn không thích sử dụng tự động cho kiểu khai báo từ trái sang phải.

auto C = Matrix(A * B); // The expression is now evaluated immediately.

1
Đó dường như là hành vi kỳ lạ để bắt đầu. Nếu tôi nhân hai ma trận, ngay cả khi thao tác lười biếng, tôi sẽ không mong muốn nó được đánh giá lại, tôi hy vọng nó sẽ duy trì trạng thái được đánh giá sau khi đánh giá ban đầu. Nếu bạn muốn thay đổi các tham số mà không sửa đổi các tham số ban đầu, cuối cùng bạn sẽ không phải xây dựng lại biểu thức chứ? Hoặc nó được thiết kế cho một loại tình huống xử lý phát trực tuyến, trong đó các tham số ban đầu liên tục thay đổi nhưng quy trình vẫn giữ nguyên?
JAB

1
Cho dù A*Bbiểu thức có được sao chép trong một autobiến hay cái gì khác hay không, hành vi bạn mô tả vẫn còn.
xtofl

Không có lỗi là do sử dụng auto.
Jim Balter

@JAB: Nó được thiết kế để hỗ trợ đơn giản hóa và phối hợp giữa các hoạt động, ví dụ, diag(A * B)không phải lãng phí chu kỳ tính toán các yếu tố ngoài đường chéo.
Ben Voigt

Tôi cũng đã phát hiện mã như 'for (auto o: vecContainer)' trong đó 'o' là một đối tượng nặng được sao chép mỗi lần. Đề xuất của tôi sẽ là sử dụng nó cho mục đích ban đầu, đó là các mẫu (với các hướng dẫn khấu trừ khó khăn) và typedef tốn nhiều công sức. Ngay cả sau đó bạn phải cẩn thận và khác biệt giữa tự động và tự động &.
dạ dày

10

Tôi sử dụng autohạn chế wihout và không gặp phải bất kỳ vấn đề nào. Tôi thậm chí đôi khi cuối cùng sử dụng nó cho các loại đơn giản như int. Điều này làm cho c ++ trở thành ngôn ngữ cấp cao hơn đối với tôi và cho phép khai báo biến trong c ++ như trong python. Sau khi viết mã python, đôi khi tôi viết

auto i = MyClass();

thay vì

MyClass i;

Đây là một trường hợp mà tôi muốn nói đó là lạm dụng autotừ khóa.

Thường thì tôi không quan tâm loại chính xác của đối tượng là gì, tôi quan tâm nhiều hơn đến tính hư cấu của nó và vì các tên hàm thường nói điều gì đó về các đối tượng chúng trả về, autokhông gây tổn thương: ví dụ: auto s = mycollection.size()tôi có thể đoán đó ssẽ là một loại số nguyên và trong trường hợp hiếm hoi tôi quan tâm đến loại chính xác, hãy kiểm tra nguyên mẫu hàm sau đó (ý tôi là, tôi muốn kiểm tra khi tôi cần thông tin, thay vì tiên nghiệm khi viết mã, chỉ trong trường hợp nó sẽ hữu ích một ngày nào đó, như trong int_type s = mycollection.size()).

Liên quan đến ví dụ này từ câu trả lời được chấp nhận:

for ( auto x = max_size; x > 0; --x )

Trong mã của tôi, tôi vẫn sử dụng autotrong trường hợp này và nếu tôi muốn xkhông dấu, thì tôi sử dụng một hàm tiện ích, có tên là say make_unsigned, thể hiện rõ mối quan tâm của tôi:

for ( auto x = make_unsigned(max_size); x > 0; --x )

từ chối trách nhiệm: Tôi chỉ mô tả việc sử dụng của tôi , tôi không đủ khả năng để đưa ra lời khuyên!


1
@ChristianRau: không mỉa mai. Lưu ý rằng tôi đã không khuyên bạn nên sử dụng auto i = MyClass().
rafak

3
Theo dõi: xem: Herbutter.com/2013/06/13/ . Việc sử dụng eg as_unsignedđược khuyến nghị ở đó, hoặc thậm chí auto w = widget{};.
rafak

3

Một trong những vấn đề lớn với chương trình C ++ là nó cho phép bạn sử dụng biến chưa được khởi tạo . Điều này dẫn chúng ta đến hành vi chương trình phi quyết định khó chịu. Cần lưu ý rằng trình biên dịch hiện đại bây giờ ném các thông báo cảnh báo / tin nhắn thích hợp nếu lốp chương trình sử dụng nó.

Chỉ để minh họa điều này, hãy xem xét bên dưới chương trình c ++:

int main() {
    int x;
    int y = 0;
    y += x;
}

Nếu tôi biên dịch chương trình này bằng trình biên dịch hiện đại (GCC), nó sẽ đưa ra cảnh báo. Cảnh báo như vậy có thể không rõ ràng nếu chúng ta đang làm việc với mã sản xuất phức tạp thực sự.

main.cpp: Trong hàm 'int main ()':

main.cpp: 4: 8: cảnh báo : 'x' được sử dụng chưa được khởi tạo trong chức năng này [-Wuninitialized]

y + = x;

    ^

================================================== =============================== Bây giờ nếu chúng ta thay đổi chương trình sử dụng tự động , sau đó biên dịch chúng ta sẽ nhận được như sau:

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: Trong hàm 'int main ()':

main.cpp: 2: 10: error : khai báo 'auto x' không có trình khởi tạo

 auto x;

      ^

Với auto, không thể sử dụng biến chưa được khởi tạo. Đây là lợi thế lớn mà chúng tôi có thể nhận được (miễn phí), nếu chúng tôi bắt đầu sử dụng tự động .

Khái niệm này và khái niệm C ++ hiện đại tuyệt vời khác được giải thích bởi chuyên gia C ++ Herb Shutter trong bài nói chuyện về CppCon14 của ông :

Quay lại vấn đề cơ bản! Yếu tố cần thiết của phong cách C ++ hiện đại


2
Đúng. Và để chỉ định loại bạn có thể khởi tạo là 0i, 0u, 0l, 0ul, 0.0f, 0.0 hoặc thậm chí int (), unsign (), double (), v.v.
Robinson

6
Lập luận này là vô lý. Bạn đang nói "bạn không thể quên trình khởi tạo vì bạn sẽ gặp lỗi trình biên dịch", nhưng điều đó đòi hỏi bạn phải nhớ sử dụng auto.
Các cuộc đua nhẹ nhàng trong quỹ đạo

1
@LightnessRacesinOrbit: Tôi nhận ra (đã học) khái niệm này từ cuộc nói chuyện của Herb Sutter. Tôi tìm thấy nó lời khuyên hợp lý / thực tế từ thảo luận, do đó nghĩ để chia sẻ với cộng đồng.
Mantosh Kumar

2
Tôi không nghĩ rằng đây là động lực tốt để sử dụng tự động. Chỉ cần bật cờ cảnh báo của trình biên dịch của bạn để sử dụng các biến chưa được khởi tạo và giải quyết tất cả các cảnh báo. Điều đó không có nghĩa là bạn không nên sử dụng auto- nhưng bạn không cần nó để giải quyết vấn đề này.
einpoklum

2

Một mối nguy hiểm tôi đã lưu ý là về các tài liệu tham khảo. ví dụ

MyBigObject& ref_to_big_object= big_object;
auto another_ref = ref_to_big_object; // ?

Vấn đề là other_Vf không thực sự là một tài liệu tham khảo trong trường hợp này, đó là MyBigObject thay vì MyBigObject &. Bạn cuối cùng sao chép một đối tượng lớn mà không nhận ra nó.

Nếu bạn đang nhận được một tài liệu tham khảo trực tiếp từ một phương pháp, bạn có thể không nghĩ về nó thực sự là gì.

auto another_ref = function_returning_ref_to_big_object();

bạn sẽ cần "tự động &" hoặc "const auto &"

MyBigObject& ref_to_big_object= big_object;
auto& another_ref = ref_to_big_object;
const auto& yet_another_ref = function_returning_ref_to_big_object();

1

Sử dụng autoở nơi có ý nghĩa cho một loại được suy ra. Nếu bạn có thứ gì đó mà bạn biết là số nguyên hoặc bạn biết đó là một chuỗi, chỉ cần sử dụng int / std :: string, v.v. Tôi sẽ không lo lắng về việc "lạm dụng" một tính năng ngôn ngữ trừ khi nó đến mức vô lý, hoặc mã obfuscates.

Dù sao đó cũng là ý kiến ​​của tôi.


4
"nơi nó có ý nghĩa ..." là phần khó khăn. Các lập trình viên có thể bị cuốn vào các chi tiết của mã hóa, họ mất bất kỳ ý nghĩa nào về ý nghĩa đối với các lập trình viên khác trong các nhà bảo trì tương lai.
DarenW

Điều đó đúng, mặc dù tôi nghĩ nó khá dễ để nói khi nó mơ hồ. Khi nghi ngờ, hãy sử dụng một bình luận!
LainIwakura

1
Nó sẽ không có ý nghĩa để sử dụng một loại?
Mikhail

Một số nhà phát triển sẽ nói rằng loại này luôn luôn phải được suy luận!
Arafangion

Sử dụng một bình luận ...... hoặc chỉ sử dụng loại và không cần bình luận?
dùng997112

1

autotừ khóa chỉ có thể được sử dụng cho biến cục bộ, không phải cho các đối số hoặc thành viên lớp / cấu trúc. Vì vậy, nó là an toàn và khả thi để sử dụng chúng bất cứ nơi nào bạn muốn. Tôi sử dụng chúng rất nhiều. Loại được suy luận tại thời gian biên dịch, trình gỡ lỗi hiển thị loại trong khi gỡ lỗi, sizeofbáo cáo chính xác, decltypesẽ cung cấp loại chính xác - không có hại. Tôi không được tính autolà quá lạm dụng!


0

TL; DR: Xem quy tắc ngón tay cái ở phía dưới.

Các câu trả lời được chấp nhận gợi ý các nguyên tắc sau của ngón tay cái:

Sử dụng autobất cứ khi nào thật khó để nói cách viết loại từ cái nhìn đầu tiên, nhưng loại phía bên phải của biểu thức là rõ ràng.

Nhưng tôi sẽ nói rằng đó là quá hạn chế. Đôi khi tôi không quan tâm đến các loại, vì tuyên bố là đủ thông tin mà tôi không bận tâm dành thời gian để tìm ra loại. Ý tôi là gì? Hãy xem xét ví dụ đã xuất hiện trong một số câu trả lời:

auto x = f();

Điều gì làm cho đây là một ví dụ về việc sử dụng sai auto? Có phải là sự thiếu hiểu biết của tôi f()về loại trả lại? Chà, nó thực sự có thể giúp nếu tôi biết điều đó, nhưng - đó không phải là mối quan tâm chính của tôi. Nhiều hơn một vấn đề là điều đó xf()khá vô nghĩa. Nếu chúng ta có:

auto nugget = mine_gold();

thay vào đó, sau đó tôi thường không quan tâm liệu kiểu trả về của hàm có rõ ràng hay không. Đọc tuyên bố, tôi biết những gì tôi đang làm và tôi biết đủ về ngữ nghĩa của giá trị trả về để không cảm thấy tôi cũng cần biết loại của nó.

Vì vậy, câu trả lời của tôi là: Sử dụng autobất cứ khi nào trình biên dịch cho phép, trừ khi:

  • Bạn cảm thấy tên biến cùng với biểu thức khởi tạo / gán không cung cấp đủ thông tin về những gì câu lệnh đang làm.
  • Bạn cảm thấy tên biến cùng với biểu thức khởi tạo / gán cung cấp thông tin "sai lệch" về loại nên là - nghĩa là, nếu bạn phải đoán cái gì đến thay vì tự động, bạn sẽ có thể đoán - và nó sẽ là sai và giả định sai này có hậu quả sau đó trong mã.
  • Bạn muốn buộc một loại khác (ví dụ: một tài liệu tham khảo).

Và cũng:

  • Thích đặt tên có ý nghĩa (không chứa tên loại khóa học) trước khi thay thế autobằng loại cụ thể.

-3

Một trong những trải nghiệm cay đắng của tôi autosử dụng nó với các biểu thức lambda :

auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!

Trên thực tế, ở đây iđược giải quyết để con trỏ chức năng của int(*)(). Đây chỉ là một đơn giản cout, nhưng chỉ cần tưởng tượng loại lỗi biên dịch / thời gian chạy xấu mà nó có thể gây ra khi sử dụng template.

Bạn nên tránh auto với các biểu thức như vậy và đặt một returnloại thích hợp (hoặc được kiểm soát decltype())

Sử dụng đúng cho ví dụ trên sẽ là,

auto i = []() { return 0; }(); // and now i contains the result of calling the lambda  

7
Bạn đã làm một công việc khủng khiếp để giải thích những gì phải làm với ô tô. Bạn đã tạo một chức năng và sau đó in nó ... Được chứ?
Dennis Zickefoose

5
@iammilind: và điều đó có liên quan gì đến auto?
R. Martinho Fernandes

7
Tôi thấy rất khó có khả năng người ta muốn đặt ()cuối cùng. Lambdas ở đó để hoạt động như các chức năng và đó là nơi chuyển đổi con trỏ chức năng đến từ. Nếu bạn muốn gọi nó ngay lập tức, tại sao lại sử dụng lambda? auto i = 0;hoạt động khá tốt.
R. Martinho Fernandes

4
Ít nhất bạn có thể mô tả một kịch bản auto x = []() { /* .... whatever goes in here ... */ }()tốt hơn auto x = /* .... whatever goes in here ... */;, ví dụ, điều tương tự, không có lambda? Tôi thấy điều đó khá vô nghĩa, vì cùng một lý do auto x = 42 + y - 42là vô nghĩa.
R. Martinho Fernandes

6
-1 đây không phải là lỗi của auto. Loại lambda không thể đánh vần nên tự động là bắt buộc , nếu bạn quên gọi hàm thì đó là cái nhìn của riêng bạn! Bạn có thể đặt một con trỏ hàm không được gọi vào một bản in C giống như một cách ngớ ngẩn.
spraff
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.