Tại sao tôi không nên #include <bits / stdc ++. H>?


267

Tôi đã đăng một câu hỏi với mã của mình mà chỉ #includethị của nó là như sau:

#include <bits/stdc++.h>

Giáo viên của tôi bảo tôi làm điều này, nhưng trong phần bình luận tôi được thông báo rằng tôi không nên.

Tại sao?


72
Huh. Tôi nên biết rằng sẽ có một phiên bản bao gồm using namespace std;ngoài đó ở đâu đó.
dùng4581602

1
Tại sao tiêu đề này thậm chí còn tồn tại? chắc chắn không có tiêu chuẩn nào bao gồm thực sự bao gồm điều này, vì nó sẽ mang lại rất nhiều rác? và nếu nó không được bao gồm bởi bất kỳ công chúng nào bao gồm ... thì tại sao nó lại được vận chuyển trong bản phân phối?
Chris Beck

10
@ChrisBeck: Đây là một chi tiết triển khai. Đây không phải là một phần của "API công khai" hoặc có nghĩa là để sử dụng. Nhưng nó vẫn phải được vận chuyển nếu không sẽ không có gì hoạt động. Tiêu chuẩn bao gồm có thể không sử dụng riêng lẻ nhưng nó có để sử dụng trong các tiêu đề được biên dịch trước. Xem bình luận ở trên cùng, có nội dung: "Đây là tệp triển khai cho tiêu đề được biên dịch trước." .
Các cuộc đua nhẹ nhàng trong quỹ đạo

1
@LightnessRacesinOrbit Nếu bạn không nên tự mình sử dụng nó, sự tồn tại của nó giúp ích gì với PCH? Hoặc gcc đủ thông minh để tự động chuyển sang nó cho mục đích PCH trong một số trường hợp?
Daniel H

2
@LightnessRacesinOrbit "Đây không phải là một phần của" API công khai "hoặc có nghĩa là để sử dụng." Hoàn toàn sai, nó dành cho mục đích sử dụng công cộng, như một tiêu đề được biên dịch trước. Libstdc ++ (pre) biên dịch và cài đặt một phiên bản được biên dịch trước của tiêu đề đó, vì vậy nếu bạn bao gồm nó thì G ++ thực sự sẽ bao gồm bits/stdc++.h.gchthay vào đó, phiên bản được biên dịch trước. Nó tồn tại bởi vì nó phải tồn tại để có thể tạo ra phiên bản tiền biên dịch của nó.
Jonathan Wakely

Câu trả lời:


311

Kể cả <bits/stdc++.h> dường như là một điều ngày càng phổ biến để thấy trên Stack Overflow, có lẽ là thứ mới được thêm vào chương trình giảng dạy quốc gia trong năm học hiện tại.

Tôi tưởng tượng những lợi thế được đưa ra một cách mơ hồ như vậy:

  • Bạn chỉ cần viết một #include dòng
  • Bạn không cần phải tra cứu tiêu đề nào

Thật không may, đây là một hack lười biếng, đặt tên trực tiếp cho tiêu đề nội bộ GCC thay vì các tiêu đề tiêu chuẩn riêng lẻ như <string>, <iostream><vector>. Nó phá hỏng tính di động và nuôi dưỡng những thói quen khủng khiếp.

Những nhược điểm bao gồm:

  • Nó có thể sẽ chỉ hoạt động trên trình biên dịch đó
  • Bạn không biết nó sẽ làm gì khi bạn sử dụng nó, bởi vì nội dung của nó không được đặt theo tiêu chuẩn
  • Thậm chí chỉ cần nâng cấp trình biên dịch của bạn lên phiên bản tiếp theo của chính nó cũng có thể phá vỡ chương trình của bạn
  • Mỗi tiêu đề đơn phải được phân tích cú pháp và biên dịch cùng với mã nguồn của bạn, tốc độ chậm và dẫn đến việc thực thi cồng kềnh trong các cài đặt biên dịch nhất định

Đừng làm thế!


Thêm thông tin:

Ví dụ về lý do tại sao Quora là xấu:


77
"có lẽ một cái gì đó mới được bổ sung vào chương trình giảng dạy quốc gia trong năm học hiện tại" mù dẫn người mù :(
Khôi phục Monica


32
Chỉ cần đến đây thông qua một lỗ sâu đục trong một câu hỏi khác, rất tốt. Điều làm cho thói quen giảng dạy này tồi tệ hơn là nó thường được theo sau bởi một trực tiếp using namesapce std;. Chỉ cần hai dòng trong và hầu như mọi định danh đẹp đều được sử dụng. Vô cùng bực bội khi thấy nó được dạy.
Người kể chuyện - Unslander Monica

6
Về ví dụ quora, nó có thể đã thay đổi theo thời gian. Tôi đã truy cập trang hôm nay và cả ưu và nhược điểm của <bits / stdc ++. H> được liệt kê trong bối cảnh cụ thể của các cuộc thi lập trình trực tuyến. Tôi thấy kết luận của họ ok-ish.
YSC

4
@EvgeniSergeev: 2KiB có rất nhiều mã, dữ liệu, thông tin ký hiệu, v.v., khi cố gắng xác định tác dụng của nó. Bạn có hiểu mọi thứ đang được thêm vào không? Đối với trình biên dịch của bạn? Bản phát hành hiện tại? Tất cả phát hành ở giữa? Tất cả các bản phát hành trong tương lai? Nếu bạn cần quyết định giữa sự thuận tiện và tính chính xác, chỉ có một lựa chọn hợp lệ duy nhất.
IInspectable

48

Tại sao? Bởi vì nó được sử dụng như thể nó được coi là một tiêu đề tiêu chuẩn C ++, nhưng không có tiêu chuẩn nào đề cập đến nó. Vì vậy, mã của bạn là không di động bằng cách xây dựng. Bạn sẽ không tìm thấy bất kỳ tài liệu nào cho nó trên cppreference . Vì vậy, nó có thể không tồn tại. Đó là một sự tưởng tượng của trí tưởng tượng của một ai đó :)

Tôi đã phát hiện ra - với sự kinh hoàng và hoài nghi của tôi - rằng có một trang web hướng dẫn nổi tiếng nơi mọi ví dụ về C ++ dường như bao gồm tiêu đề này . Thế giới thật điên rồ. Đó là bằng chứng.


Để bất cứ ai viết "hướng dẫn" như vậy

Hãy ngừng sử dụng tiêu đề này. Quên nó đi. Đừng truyền bá sự điên rồ này. Nếu bạn không muốn hiểu tại sao làm điều này là sai , hãy tin tôi đi. Tôi không ổn khi bị đối xử như một người có thẩm quyền đối với bất cứ điều gì, và tôi có lẽ chỉ toàn một nửa thời gian, nhưng tôi sẽ chỉ tạo ra một ngoại lệ trong trường hợp này. Tôi khẳng định rằng tôi biết những gì tôi đang nói ở đây. Đưa tôi vào lời nói của tôi. Tôi khẩn cầu bạn.

Tái bút: Tôi cũng có thể tưởng tượng ra "tiêu chuẩn giảng dạy" ghê tởm nơi ý tưởng độc ác này có thể xảy ra, và hoàn cảnh dẫn đến nó. Chỉ vì dường như có một nhu cầu thực tế cho nó không làm cho nó được chấp nhận - thậm chí không cần nhìn lại.

PPS Không, không có nhu cầu thực tế cho nó. Không có nhiều tiêu đề C ++ tiêu chuẩn và chúng được ghi lại rõ ràng. Nếu bạn dạy, bạn đang làm cho học sinh của mình trở thành một kẻ bất đồng bằng cách thêm "phép thuật" đó. Sản xuất các lập trình viên với một tư duy kỳ diệu là điều cuối cùng chúng tôi muốn. Nếu bạn cần cung cấp cho sinh viên một tập hợp con C ++ để làm cho cuộc sống của họ dễ dàng hơn, chỉ cần tạo ra một bản hướng dẫn với danh sách ngắn các tiêu đề áp dụng cho khóa học bạn dạy và với tài liệu ngắn gọn cho các cấu trúc thư viện mà bạn mong đợi các sinh viên sẽ sử dụng.


35

Có một trang web Stack Exchange được gọi là Lập trình Câu đố & Code Golf . Các câu đố lập trình trên trang web đó phù hợp với định nghĩa của câu đố này :

một món đồ chơi, vấn đề, hoặc một kế hoạch khác được thiết kế để giải trí bằng cách đưa ra những khó khăn cần được giải quyết bằng sự khéo léo hoặc nỗ lực kiên nhẫn.

Chúng được thiết kế để giải trí, và không phải theo cách mà một lập trình viên làm việc có thể bị thích thú bởi một vấn đề trong thế giới thực gặp phải trong công việc hàng ngày của họ.

Mã Golf là "một loại cuộc thi lập trình máy tính giải trí, trong đó những người tham gia cố gắng đạt được mã nguồn ngắn nhất có thể thực hiện một thuật toán nhất định." Trong các câu trả lời trên trang web PP & CG, bạn sẽ thấy mọi người chỉ định số lượng byte trong câu trả lời của họ. Khi họ tìm ra cách để loại bỏ một vài byte, họ sẽ xóa số ban đầu và ghi lại số mới.

Như bạn có thể mong đợi, phần thưởng chơi golf mã lạm dụng ngôn ngữ lập trình cực đoan. Tên biến một chữ cái. Không có khoảng trắng. Sử dụng sáng tạo các chức năng thư viện. Tính năng không có giấy tờ. Thực hành lập trình không chuẩn. Những vụ hack kinh hoàng.

Nếu một lập trình viên gửi yêu cầu kéo tại nơi làm việc có chứa mã kiểu golf, nó sẽ bị từ chối. Đồng nghiệp của họ sẽ cười nhạo họ. Người quản lý của họ sẽ ghé qua bàn của họ để trò chuyện. Mặc dù vậy, các lập trình viên tự giải trí bằng cách gửi câu trả lời cho PP & CG.

Điều này có liên quan gì stdc++.h? Như những người khác đã chỉ ra, sử dụng nó là lười biếng. Nó không khả dụng, vì vậy bạn không biết liệu nó sẽ hoạt động trên trình biên dịch của bạn hay phiên bản tiếp theo của trình biên dịch. Nó nuôi dưỡng những thói quen xấu. Nó không chuẩn, vì vậy hành vi của chương trình của bạn có thể khác với những gì bạn mong đợi. Nó có thể tăng thời gian biên dịch và kích thước thực thi.

Đây là tất cả các phản đối hợp lệ và chính xác. Vậy tại sao mọi người sẽ sử dụng sự quái dị này?

Nó chỉ ra rằng một số người thích câu đố lập trình mà không có mã golf . Họ gặp nhau và cạnh tranh tại các sự kiện như ACM-ICPC, Google Code Jam và Facebook Hacker Cup hoặc trên các trang web như Topcoder và Codeforces. Thứ hạng của họ dựa trên tính chính xác của chương trình, tốc độ thực hiện và tốc độ họ gửi giải pháp. Để tối đa hóa tốc độ thực hiện, nhiều người tham gia sử dụng C ++. Để tối đa hóa tốc độ mã hóa, một số trong số họ sử dụng stdc++.h.

Đây có phải là một ý tưởng tốt? Hãy kiểm tra danh sách các nhược điểm. Tính di động? Không thành vấn đề vì các sự kiện mã hóa này sử dụng một phiên bản trình biên dịch cụ thể mà các thí sinh biết trước. Tuân thủ tiêu chuẩn? Không liên quan đến một khối mã có tuổi thọ hữu ích dưới một giờ. Biên dịch thời gian và kích thước thực thi? Đây không phải là một phần của phiếu điểm của cuộc thi.

Vì vậy, chúng ta còn lại với những thói quen xấu. Đây là một phản đối hợp lệ. Bằng cách sử dụng tệp tiêu đề này, các thí sinh sẽ tránh được cơ hội tìm hiểu tệp tiêu đề chuẩn xác định chức năng họ đang sử dụng trong chương trình của họ. Khi họ viết mã trong thế giới thực (và không sử dụng stdc++.h), họ sẽ phải dành thời gian tìm kiếm thông tin này, điều đó có nghĩa là họ sẽ làm việc kém hiệu quả hơn. Đó là nhược điểm của việc luyện tập với stdc++.h.

Điều này đặt ra câu hỏi tại sao nó đáng tham gia vào lập trình cạnh tranh nếu nó khuyến khích các thói quen xấu như sử dụng stdc++.hvà vi phạm các tiêu chuẩn mã hóa khác. Một câu trả lời là mọi người làm điều đó vì lý do tương tự họ đăng các chương trình trên PP & CG: một số lập trình viên thấy thú vị khi sử dụng các kỹ năng mã hóa của họ trong bối cảnh giống như trò chơi.

Vì vậy, câu hỏi về việc có nên sử dụng stdc++.hhay không là liệu tốc độ mã hóa có mang lại lợi ích trong một cuộc thi lập trình có vượt qua các thói quen xấu mà người ta có thể phát triển bằng cách sử dụng nó hay không.

Câu hỏi này hỏi: "Tại sao tôi không #incolee <bits/stdc++.h>?" Tôi nhận ra rằng nó đã được hỏi và trả lời để đưa ra quan điểm và câu trả lời được chấp nhận nhằm mục đích là Câu trả lời đúng cho câu hỏi này. Nhưng câu hỏi không phải là "Tại sao tôi không #incolee <bits/stdc++.h>trong mã sản xuất?" Do đó, tôi nghĩ thật hợp lý khi xem xét các kịch bản khác trong đó câu trả lời có thể khác nhau.


5
Tôi đã ủng hộ rồi, nhưng có lẽ đáng để chỉ ra rằng "cho vui" là một lý do tốt để tham gia vào chương trình cạnh tranh. Mặt khác, "để gây ấn tượng với một nhà tuyển dụng tiềm năng" thì không - nó sẽ chủ động gây hại cho trường hợp của bạn với tôi.
Martin Bonner hỗ trợ Monica

2
@MartinBonner Tôi biết một số nhà quản lý tuyển dụng xem kinh nghiệm lập trình cạnh tranh là một lá cờ đỏ. Nhưng miễn là các công ty phần mềm hàng đầu sử dụng các vấn đề theo kiểu CP trong các cuộc phỏng vấn và điều hành các cuộc thi lập trình để tìm kiếm tân binh, CP sẽ tiếp tục phổ biến trong các nhà phát triển đầy tham vọng.
RedGreenCode

@RedGreenCode Tôi không phải là người quản lý (cảm ơn $ DEITY), nhưng đôi khi tôi có ảnh hưởng đến việc thuê các mong muốn. Và tôi chắc chắn thấy bất kỳ tài liệu tham khảo nào về "lập trình cạnh tranh" là một lá cờ đỏ khổng lồ - không phải là một lợi thế.
Jesper Juhl

3
@JesperJuhl Nếu người phỏng vấn kỹ thuật tại công ty của bạn sử dụng các câu đố thuật toán trong các cuộc phỏng vấn của họ (như nhiều người làm), điều đó mang lại lợi thế cho ứng viên có kinh nghiệm lập trình cạnh tranh. Có thể lựa chọn hợp lý cho các ứng viên là tham gia CP nhưng tránh đề cập đến nó trong sơ yếu lý lịch / CV của họ.
RedGreenCode

2
Mặc dù sự thật là tiêu đề này có thể được sử dụng trong một số chương trình cạnh tranh, nhưng nó không hoàn toàn đến từ đâu. Nó đến từ một lớp học. Và bất cứ ai dạy trong lớp học đó cũng có đủ ảnh hưởng để gây ô nhiễm - thông qua dòng thác theo sau - hàng chục nếu không phải hàng trăm ngàn học sinh (bằng cách giáo dục các giáo viên và đồng nghiệp, những người sau đó, vô tình, đã lây lan căn bệnh đó). Và bây giờ những sinh viên đó cũng đang viết hướng dẫn tại một nơi để hướng dẫn. Tôi chỉ muốn khóc ở một góc. Các trang web lập trình cạnh tranh chỉ cần có một regex để từ chối bất kỳ tiêu đề không chuẩn nào .
Phục hồi

9

Từ N4606, Bản nháp làm việc, Tiêu chuẩn cho ngôn ngữ lập trình C ++:

17.6.1.2 Tiêu đề [tiêu đề]

  1. Mỗi phần tử của thư viện chuẩn C ++ được khai báo hoặc định nghĩa (nếu thích hợp) trong một tiêu đề.

  2. Thư viện chuẩn C ++ cung cấp 61 tiêu đề thư viện C ++, như trong Bảng 14.

Bảng 14 - Tiêu đề thư viện C ++

<algorithm> <future> <numeric> <strstream>
<any> <initializer_list> <optional> <system_error>
<array> <iomanip> <ostream> <thread>
<atomic> <ios> <queue> <tuple>
<bitset> <iosfwd> <random> <type_traits>
<chrono> <iostream> <ratio> <typeindex>
<codecvt> <istream> <regex> <typeinfo>
<complex> <iterator> <scoped_allocator> <unordered_map>
<condition_variable> <limits> <set> <unordered_set>
<deque> <list> <shared_mutex> <utility>
<exception> <locale> <sstream> <valarray>
<execution> <map> <stack> <variant>
<filesystem> <memory> <stdexcept> <vector>
<forward_list> <memory_resorce> <streambuf>
<fstream> <mutex> <string>
<functional> <new> <string_view>

Không có <bits / stdc ++. H> ở đó. Điều này không có gì đáng ngạc nhiên, vì các tiêu đề <bits / ...> là chi tiết triển khai và thường mang một cảnh báo:

*  This is an internal header file, included by other library headers.
*  Do not attempt to use it directly. 

<bits / stdc ++. h> cũng mang một cảnh báo:

*  This is an implementation file for a precompiled header.
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.