Gần đây, ngành Internet đang than thở rằng đây là di chứng của 3 năm ảnh hưởng, nhiều công ty đã không thể trụ nổi qua mùa đông lạnh giá, một số vốn nước ngoài đã bắt đầu rút khỏi thị trường. hàng ngũ thất nghiệp, và do có ít công ty hơn, Nhiều người chậm nộp đơn xin việc, và không may tôi là một trong số họ. Kể từ khi bắt đầu đi làm, tôi rất bận rộn, ban đầu tôi luôn nghĩ rằng công việc chỉ để cuộc sống tốt đẹp hơn, nhưng khi nghỉ việc, tôi cảm thấy như mình đã đánh mất một thứ gì đó nên hiếm khi có nhiều thời gian rảnh rỗi như vậy. đã làm trong khoảng thời gian hai tháng qua. Một khi con người được tự do, chắc chắn họ sẽ cảm thấy có chút trống rỗng. Hầu hết nguyên nhân dẫn đến sự trống rỗng này là do lo lắng về tương lai, chẳng hạn như lo lắng về lượng thức ăn dư thừa trong túi và lo lắng rằng những người làm việc chăm chỉ sẽ nhìn họ với ánh mắt khinh thường. Vì vậy, trong khoảng thời gian này, tôi cũng đã thử ứng tuyển vào một số vị trí. Khi nhiều người phỏng vấn hỏi cách thực hiện khuôn khổ đơn giản, thành thật mà nói, tôi không thể diễn đạt chính xác những gì họ muốn biết. Một mặt, tôi thiếu khả năng hùng biện. Một mặt, quả thực là vì đã lâu quá nên tôi đã quên nhiều thứ. Đừng thắc mắc tại sao bạn lại quên những gì mình đã viết. Ví dụ, tôi tin rằng hầu hết mọi người không thể giải thích được cách bố cục hay hoặc phương pháp giải quyết vấn đề mà họ đã nghĩ đi nghĩ lại sau giờ làm việc. Trí nhớ của con người có hạn, nếu không sẽ không có câu nói nổi tiếng rằng trí nhớ tốt không bằng viết dở. Kế hoạch tái cấu trúc đơn giản thực sự xuất hiện khi C++ đang chuẩn bị phát hành tiêu chuẩn C++20 vào năm 2019. Việc đưa ra khái niệm mô-đun mô-đun mang lại cho tôi những kỳ vọng rất tốt cho việc phát triển thư viện. Đặc biệt từ đầu năm ngoái tôi đã chú ý đến C++23 nên năm ngoái tôi quyết định hoàn thành việc xây dựng lại plain trong năm nay Số phiên bản đã được nâng cấp trực tiếp lên plain2.0. với plain1.1rc hiện tại Đã có khá nhiều thay đổi. Điều tôi muốn nói là một trong những mục đích của việc xây dựng lại khuôn khổ này là để lấy lại trí nhớ của tôi và hoàn thành một phần mục tiêu đã đặt ra. Nó cũng là để nâng cao kỹ năng của tôi về C++ hiện đại. Tôi hy vọng có thể học hỏi và thảo luận các vấn đề về thiết kế với tôi. bạn bè ở đây có một số câu hỏi. Đồng thời, tuy rằng hoàn cảnh chung không tốt, nhưng trong lòng vẫn nên có hy vọng, sau mùa đông lạnh giá sẽ có mùa xuân, những nơi tuyệt vọng tự nhiên sẽ có sức sống. hãy thay đổi suy nghĩ và hoàn thiện bản thân hơn là tự trách mình một cách mù quáng (Tất nhiên, điều này không có nghĩa là lăn lộn). Tôi tin rằng tương lai luôn tươi sáng Tôi cầu chúc cho những người bạn đang thất nghiệp hoặc sắp thất nghiệp có công việc và cuộc sống tốt đẹp, và tôi cũng cầu chúc những người đang đi làm hoặc không có nhu cầu đi làm một cuộc sống hạnh phúc. Đồng thời, tôi cũng mong rằng loạt bài này (tôi có thể viết vài bài) có thể mang lại lợi ích nào đó cho mọi người. Nhân tiện, loạt bài viết này không phải là nền tảng để học C++. Nó có thể yêu cầu bạn phải có một mức độ hiểu biết nhất định về ngôn ngữ này. Chuỗi bài viết này chủ yếu chia sẻ một số kinh nghiệm của tôi trong quá trình phát triển và thiết kế. có lỗi, mong các bạn để lại lời nhắn ở phần bình luận hoặc tham gia nhóm để liên hệ với mình. Trước đây tôi chưa viết bài chi tiết về vấn đề này, chủ yếu là vì tôi quá lười biếng, nhưng bây giờ tôi viết bài này vì khi con người đến một độ tuổi nhất định, đã đến lúc tổng kết lại một điều gì đó, bên cạnh đó, nếu khủng hoảng tuổi trung niên xảy ra. không giảm bớt, Internet có thể không thể Đây là nơi tôi ở và tôi hy vọng sẽ để lại một số kiến thức hữu ích ở đây để mọi người có thể có những hiểu biết nhất định về lập trình mạng. (Bài viết này mất gần một ngày. Có vẻ như khả năng phản ứng của tôi đã giảm sút. Nếu thấy hữu ích, bạn có thể chú ý đến. Tôi sẽ tiếp tục chia sẻ trong tương lai).
lý do
Nhược điểm của plain1.1rc
1. Vấn đề về không gian tên
Nếu bạn đã nhìn thấy hoặc liên hệ với những người bạn đơn giản, không khó để nhận ra rằng các không gian tên đều bắt đầu bằng pf_*. Khi nói về vấn đề này, chúng ta vẫn phải bắt đầu với tiền thân của plain, plainserver (https://github.com/viticm/plainserver). Tôi nhìn thời gian, ừm…, thời điểm đó là khoảng chín năm trước, khi tôi còn sống ở một thành phố ven biển phía Nam. Ngay từ cái tên có thể dễ dàng liên tưởng đến một máy chủ. Dự án này rất có mục tiêu và triển khai một mô hình chung về máy chủ, máy chủ trò chơi ở chế độ đa tiến trình và đa luồng. Bộ mô hình này là mô hình mà ngày nay nhiều nhà sản xuất cũ (Sohu, Kingsoft, v.v.) vẫn có thể sử dụng. Lý do áp dụng nó nói chung là vì các công ty này được thành lập sớm và đã cảm thấy thoải mái khi áp dụng mô hình này trong vấn đề này (những công ty trưởng thành tương đối đáng tin cậy và các công ty không sẵn sàng chấp nhận rủi ro để thử, dù sao thì việc thử cũng phải trả giá) . Những người bạn quan tâm có thể muốn xem qua cách triển khai mà tôi đã đề cập đến kiến trúc này trong bài viết trước và chỉ đơn giản là vẽ mô hình của nó bằng hình ảnh.
Bạn cũng có thể xem thư mục chung của plainserver, cấu trúc của thư mục này, sau đó so sánh nó với các thư mục trong plainserver. Bạn có cảm thấy có nhiều điểm tương đồng không? Đúng vậy, plain có nguồn gốc từ thư viện chung, tinh tế hơn, trừu tượng hơn và được chia sẻ ban đầu tồn tại như một thư viện chung cho máy khách và máy chủ. Sau đó, câu hỏi quan trọng xuất hiện. Mở tệp và xem tệp common/src/common/base/log.cc. Không khó để tìm thấy không gian tên ps_common_base {. quy tắc. Đây là tôi. Sau khi đọc các tiêu chuẩn mã hóa của Google C++, tôi đã nghĩ ra một quy tắc đặt tên. Không khó để nhận ra rằng quy tắc ở đây là ps (tên dự án)_common (thư mục mẹ)_base (thư mục con).
Từ các quy tắc không gian tên ở trên, không khó để nhận ra rằng không gian tên hiện tại của plain thực sự được điều chỉnh một chút trên cơ sở này. Kể từ khi tiếp xúc với không gian tên, tôi đã cố gắng hết sức để bọc các hàm hoặc đối tượng nhằm giảm xung đột giữa các mô-đun. Nhưng nếu chúng ta chia nó hoàn toàn theo không gian tên và cấu trúc thư mục thì hệ thống phân cấp thư mục chắc chắn sẽ được lồng sâu vào nhau. Do đó, khi đơn giản, người ta quy định rằng việc lồng các thư mục phải nhỏ hơn ba cấp độ, điều này cũng hạn chế việc lồng các không gian tên. Điều này tạo thành một loạt các không gian tên như pf_basic, pf_sys, v.v., và cũng có các pf_sys::thread lồng nhau hai cấp độ. Tôi quên đề cập rằng PF thực sự là tên viết tắt của plain framework. Thành thật mà nói, không có vấn đề gì khi đặt tên nó theo cách này. Tuy nhiên, trong quá trình sử dụng, bạn sẽ thấy một số không gian tên và phương thức có tên trùng lặp, chẳng hạn như mô-đun tệp đóng gói một số giao diện thao tác tệp đa nền tảng, như sau:
。
không gian tên
tập tin pf {
không gian tên
api { PF_API int32_t openex(
hằng số
char
*
tên tệp, cờ int32_t); PF_API int32_t openmode_ex(
hằng số
char
*
tên tệp, cờ int32_t, chế độ int32_t); PF_API
vô hiệu
closeex(int32_t fd); PF_API uint32_t readex(int32_t fd,
vô hiệu
*
bộ đệm, độ dài uint32_t); PF_API uint32_t writeex(int32_t fd,
hằng số
vô hiệu
*
bộ đệm, độ dài uint32_t); PF_API int32_t fcntlex(int32_t fd, int32_t cmd); PF_API int32_t fcntlarg_ex(int32_t fd, int32_t cmd, int32_t arg); PF_API
bool
lấy_không_chặn_ex(int32_t socketid); PF_API
vô hiệu
thiết lập_không_chặn_ex(int32_t socketid,
bool
trên); PF_API
vô hiệu
ioctlex(int32_t fd, int32_t yêu cầu,
vô hiệu
*
argp); PF_API uint32_t availableex(int32_t fd); PF_API int32_t dupex(int32_t fd); PF_API int64_t lseekex(int32_t fd, uint64_t offset, int32_t từ đâu); PF_API int64_t tellex(int32_t fd); PF_API
bool
cắt ngắn(
hằng số
char
*
tên tệp); PF_API nội tuyến
bool
tồn tại(
hằng số
tiêu chuẩn::
sợi dây
&
tên tệp) { tự động fp
= fopen(tên tệp.c_str(),
"
r
"
);
nếu như
(là_null(fp))
trở lại
SAI
; fclose(fp); fp
=
giá trị rỗng;
trở lại
ĐÚNG VẬY
; } }
//
không gian tên api
}
//
không gian tên pf_file
。
Nói chung, không có vấn đề gì với quy tắc đặt tên này. Nội dung được lồng vào nhau (giao diện được bao bọc rất tốt). Năm ngoái, tôi vẫn nghĩ theo cách này. Hãy thử sử dụng các không gian tên để giảm bớt những xung đột này. có vấn đề gì. Nhưng khi sử dụng, chúng ta sẽ gọi nó như pf_file::api::func, đây thực ra không phải là vấn đề lớn. Nhưng gần đây tôi thấy rằng gọi theo cách này không thuận tiện lắm. Trên thực tế, các giao diện này là sự đóng gói của các giao diện tiêu chuẩn. ex được thêm vào cuối để tránh xung đột đặt tên. tất cả. Tôi luôn cảm thấy mình đã đi quá xa đối với một gói hàng như vậy. Tôi nghĩ thư mục này chỉ nhằm mục đích phân loại tốt hơn để người dùng có thể nhanh chóng xác định vị trí của nó và nó không liên quan gì đến không gian tên. Tôi nghĩ nó không cần phải được bao bọc quá sâu khi gọi. góc nhìn của người dùng, đơn giản:: Chỉ cần gọi func như thế này. Trên thực tế, việc thay đổi quy tắc này dựa trên sự hiểu biết của tôi về std. Không phải mọi thứ trong thư viện chuẩn đều mạnh mẽ như vậy nên sẽ thuận tiện hơn khi sử dụng.
2. Mã dự phòng
Vì lý do lịch sử, vì đơn giản có nguồn gốc từ các dự án cũ, tham chiếu đến nhiều thiết kế trước đó, nên tôi đã giữ lại nhiều phương thức đã được đóng gói trước đó bên trong khung. Mặc dù những phương thức này có thể không được sử dụng trong khung nhưng tôi nghĩ rằng người dùng có thể sử dụng nó. trong dự án nên được giữ lại nên điều này tạo ra rất nhiều sự dư thừa. Sau khi xem xét một số dự án nguồn mở, tôi thấy rằng độ dư thừa mã trong hầu hết các dự án nguồn mở là rất thấp. Ngoại trừ việc triển khai và các giao diện bên ngoài mà khung yêu cầu, mọi phương thức và lớp dự phòng đều không được xem xét. Giảm mã không có nghĩa là giảm chức năng mà còn giảm chi phí bảo trì và sự nhầm lẫn của người dùng. Suy cho cùng, khi người dùng gặp quá nhiều giao diện, hầu hết họ đều bối rối. Điều này thực ra cũng giống như "C++ hiệu quả" (tôi mới đọc được hai tháng nay, tôi sẽ giới thiệu một hoặc hai cuốn sách bên dưới) Mục 18. : Làm cho giao diện dễ sử dụng Phù hợp với nguyên tắc sử dụng đúng cách và khó sử dụng không chính xác Tôi nghĩ rằng giao diện càng ít và tinh tế thì người dùng càng dễ sử dụng chúng một cách chính xác. cách để đạt được sự đơn giản.
Đối với mã dư thừa, phương pháp của 2.0 đơn giản là xóa và giữ lại nó, xóa một số giao diện không liên quan và để lại một số thứ thực sự hữu ích. Bởi vì sau C++ 23, có rất nhiều điều thú vị trong thư viện chuẩn, chẳng hạn như đối với những thứ đã được triển khai, ban đầu tôi muốn sử dụng StringPiece của Google trong plain1.1 của C++ 11 để thực hiện một số tối ưu hóa nhất định, nhưng không sao. Để cải thiện các tiêu chuẩn, string_view được đưa vào C++ 17, do đó, điều này không yêu cầu đóng gói bổ sung. Cũng vì lý do này mà plain2.0d thực hiện nâng cấp phiên bản chính cho mục đích thử nghiệm và loại bỏ mã thừa. Đặc biệt là các tệp như .tcc, tôi dự định loại bỏ tất cả và đưa phần triển khai mẫu vào .h.
Sử dụng thư viện chuẩn có thể giải quyết tốt hơn các vấn đề đa nền tảng, vì thư viện chuẩn giúp chúng ta triển khai nhiều giao diện không có trong C++98 hoặc C++03. Ví dụ: chúng được gói gọn trong C++11 std:: thread. Trước đây, khi viết đa nền tảng, bạn cần phải làm quen với pthread và các API luồng tương ứng, chẳng hạn như windows. Trong phiên bản 1.0 thuần túy, việc tạo luồng là gọi API hệ thống, cho phép bạn hoặc người dùng đọc các thông tin liên quan. mã nguồn Sương mù. Thời đại đang phát triển và các tiêu chuẩn cũng đang được cập nhật. Sau sự ra đời của ChatGTP, ứng dụng này đã trở nên phổ biến vào cuối năm ngoái, chúng ta sẽ thấy rằng thời đại của chúng ta đang ở trong thời kỳ phát triển nhanh chóng của cuộc cách mạng công nghiệp công nghệ. cần thiết để theo kịp thời đại và thử hoặc hiểu nó. Một số công nghệ mới tiên tiến, ngay cả khi công nghệ chưa hoàn thiện lắm, có thể mang lại cho bạn một sự cải tiến nhất định.
。
3. Mẫu thiết kế
Ngoài ra, vì nó dựa trên một dự án cũ, vì plain dựa trên thư viện chung nên thư viện này có nhiều tính năng phù hợp trước đây. Do đó, khi nói đến các mẫu thiết kế, chúng ta vẫn luôn đi đầu trong suy nghĩ của nó. Nếu muốn bắt đầu với những sai sót của các mẫu thiết kế, chúng ta cũng có thể xem xét việc triển khai đoạn mã sau:
#bao gồm
"
pf/engine/config.h
"
#bao gồm
"
pf/db/config.h
"
#bao gồm
"
pf/script/config.h
"
#bao gồm
"
pf/net/kết nối/quản lý/config.h
"
#bao gồm
"
pf/net/giao thức/config.h
"
#bao gồm
"
pf/cache/manager.h
"
#bao gồm
"
pf/cơ bản/kiểu/biến.h
"
#bao gồm
"
pf/console/config.h
"
không gian tên
động cơ pf {
lớp học
Hạt nhân PF_API:
công cộng
pf_basic::Singleton< Hạt nhân >
{
công cộng
: Hạt nhân();
ảo
~
Hạt nhân();
công cộng
:
tĩnh
Hạt nhân &
getsingleton();
tĩnh
Hạt nhân *
lấy con trỏ_singleton();
công cộng
:
ảo
bool
nhiệt();
ảo
vô hiệu
chạy();
ảo
vô hiệu
dừng lại();
công cộng
: pf_net::connection::manager::Basic
*
lấy_mạng() {
trở lại
mạng lưới_.
lấy
(); }; pf_db::Giao diện
*
lấy_db(); pf_cache::Quản lý
*
lấy_bộ_bạc() {
trở lại
bộ nhớ đệm_.
lấy
(); }; pf_script::Giao diện
*
lấy_script(); pf_db::Nhà máy
*get_db_factory() {
trở lại
nhà máy_db.
lấy
(); } pf_script::Nhà máy
*lấy_kịch_bản_nhà_sản() {
trở lại
nhà máy_script_.
lấy
(); } pf_console::Ứng dụng
*lấy_bản_điều_khiển() {
trở lại
bảng điều khiển_.
lấy
(); } ...
Sau khi sử dụng các hàm ảo trước đây, bạn sẽ thấy rằng các hàm ảo có nhiều hàm, bởi vì đây là một trong những cách để đạt được tính đa hình hướng đối tượng trong C++, miễn là có thể cần đến tính kế thừa trong khung. Tôi sẽ thêm Hàm hủy được đặt thành một hàm ảo, nhưng tôi chưa bao giờ cân nhắc liệu tính kế thừa đó có tồn tại hay không. Tôi từng nghĩ rằng người dùng có thể tùy chỉnh nó. Trên thực tế, NVI (Không có hàm ảo nào) có thể được sử dụng ở đây. giao diện) hoặc Chiến lược của std::function và phương pháp Pimpl cổ điển, việc bộc lộ quá nhiều thứ cần kế thừa thực sự làm tăng gánh nặng cho người dùng. Khi thiết kế các lớp, các mẫu thiết kế trong plain1.1rc đều dựa trên hy vọng rằng người dùng sẽ ghi đè các hàm ảo để đạt được các triển khai tùy chỉnh. Lớp thậm chí còn chứa một số lượng lớn các biến thành viên được bảo vệ. đóng gói. Nó có thể gây ra sự cố tương thích ABI (Giao diện nhị phân ứng dụng) trong quá trình nâng cấp thư viện.
Để đóng gói thư viện tốt hơn, tôi đã nghĩ đến việc sử dụng triển khai xuất và nhập trong mô-đun mà C++ 20 bắt đầu hỗ trợ. Về lý do tại sao C++ 23 không có mô-đun được sử dụng, tôi sẽ nói cụ thể về vấn đề này bên dưới. Ở đây tôi sẽ nói về một vấn đề dường như không liên quan trong việc ứng dụng các mẫu thiết kế, đó là các giao diện được thiết kế plain1.1rc liên quan đến việc đóng gói script và db Trước đây, để cho phép plain1.1rc có thể thực hiện được. to Không còn bất kỳ phần phụ thuộc nào ngoài thư viện tiêu chuẩn hệ thống. Tôi đã liệt kê các tập lệnh và gói cơ sở dữ liệu một cách riêng biệt và biến chúng thành các mô-đun trình cắm cần được sử dụng bên ngoài. Đối với các giao diện này, bạn chỉ cần tải trình cắm dưới dạng loại tùy chỉnh, sau đó bạn có thể sử dụng các giao diện tạo và vận hành được cung cấp bởi bản thân nó. Không có vấn đề gì với điều này, nhưng bây giờ có vẻ như một trình cắm được dành riêng cho. hai thư mục này hơi lãng phí, vì việc triển khai bên trong hiện tại chỉ có nhiều nhất là một hoặc hai tệp, vì vậy tôi dự định chuyển chúng vào cùng một thư mục để sử dụng như một số tiêu chuẩn giao diện bên ngoài.
sự cải tiến
mục tiêu plain2.0d
1. Đơn giản
Đơn giản là mục tiêu chính, đó là giữ cho giao diện càng đơn giản càng tốt và hiển thị càng ít thứ cho người dùng càng tốt. Do đó, có nhu cầu đóng gói tương đối cao và hầu hết các lớp có thể cần phải được thiết kế lại. Chính xác là do một số lượng lớn các lớp cần được thiết kế lại và các tiêu chuẩn mới được đưa ra nên các cải tiến lớn về phiên bản đã được thực hiện. Đối với phiên bản C++ 11, nó có thể dần dần ít được bảo trì hơn trong tương lai. Nếu bạn muốn tìm hiểu các tiêu chuẩn mới với tôi, bạn có thể chuyển sang nhánh phát triển dev. (Tính đơn giản được liệt kê là mục tiêu chính ở đây. Một số người có thể nói rằng khái niệm trước đây của plain là an toàn, nhanh chóng và đơn giản. An toàn không quan trọng sao? Câu trả lời là không, bởi vì 2.0 là một cải tiến trên cơ sở 1.1 và an toàn vẫn là điểm mấu chốt, mặc dù nó có thể không cung cấp quá nhiều đảm bảo an ninh mạnh mẽ, nhưng chắc chắn cần phải có những đảm bảo an ninh cơ bản).
Bản dịch tiếng Anh của plain được gọi là flat/simple. Người ta cũng hy vọng rằng thư viện có thể cung cấp một số giao diện đơn giản để người dùng có thể tránh được quá nhiều nhầm lẫn. Trên thực tế, việc thiết kế một giao diện đơn giản không phải là điều dễ dàng, nhiều ứng dụng phải đối mặt với những tình huống phức tạp và việc đơn giản hóa các vấn đề phức tạp cũng không phải là điều dễ dàng. Ở đây tôi phải nói về khung skynet của Fengyun. Khung này được thiết kế ngay từ đầu để xử lý việc gửi và nhận các gói tin nhắn. Người dùng chỉ cần chú ý đến một số giao diện như skynet.callback và skynet.send, nhưng khung này. Hiệu suất đạt tiêu chuẩn. Mô hình nhóm luồng Reactor+ mà anh ấy sử dụng đạt được tính đồng thời cao, đây là một trong những điều nhanh chóng mà tôi sẽ đề cập tiếp theo (độ bền không chỉ là hiệu suất). Khi tham gia vào đa luồng, việc lập trình sẽ phải đối mặt với một môi trường phức tạp và không thể tránh khỏi phải đối mặt với một số điều kiện cạnh tranh (cạnh tranh tài nguyên). Đối mặt với sự cạnh tranh về tài nguyên, chúng ta phải dùng đến phương pháp khóa của tổ tiên. Tôi sẽ đề cập ngắn gọn một số mô tả về khóa trong phần tiếp theo. Các ví dụ đưa ra ở đây chỉ minh họa rằng những gì có vẻ đơn giản có thể không đơn giản để thực hiện. Vì vậy, khi thiết kế 2.0, tôi vẫn có những cân nhắc nhất định, dẫn đến việc mã đôi khi bị viết lại nhiều lần. May mắn thay, tôi có thể loay hoay với nó trong dev.
2. Nhanh
Nhanh ở đây có hai nghĩa, một là bắt đầu nhanh, hai là hiệu suất cao. Chìa khóa để bắt đầu nhanh chóng là giao diện đơn giản và rõ ràng, đồng thời nó cũng cung cấp một số kịch bản ứng dụng đặc biệt. Ví dụ: để tạo màn hình máy chủ, bạn chỉ cần nhập tiêu đề (có thể được nhập trực tiếp trong tương lai), có thể chỉ yêu cầu một vài dòng mã. Triển khai nhanh chóng.
Vì nó là framework của thư viện mạng nên nó phải đạt được tính đồng thời cao. Trước hết, tôi muốn nói rõ ở đây rằng thư viện mạng hiện tại không xem xét đến thiết kế phân tán. triển khai thông báo có tên nsq. Bạn có thể tìm thấy nó trên github. Tính đồng thời cao không thể tăng thông lượng của mạng, nhưng nó có thể tận dụng tối đa lợi thế đa lõi của CPU để tăng tốc độ phản hồi. Do đó, việc vượt qua các hạn chế của phần cứng hoàn toàn không được xem xét. , đơn giản sử dụng giao diện ổ cắm truyền thống để triển khai mạng. Phần (giao thức là TCP) không sử dụng DPDK của Intel, một công nghệ dựa trên card mạng (theo như tôi biết thì nó được gọi là không sao chép). Khi nói đến TCP/IP, tôi phải nói thêm một điều nữa. Khi tôi còn học đại học, một trong những cuốn sách giáo khoa là Giải thích chi tiết về TCP/IP (Tập 1). đọc cuốn sách này, tôi sẽ có sự hiểu biết toàn diện về việc xây dựng mạng ngày nay. Suy cho cùng, Internet hiện nay gần như hoàn toàn dựa trên công nghệ này. Trong cuộc phỏng vấn, bạn có thể được hỏi về bắt tay ba chiều (SYN, SYN+ACK, ACK) và sóng bốn chiều. Bạn thậm chí có thể được hỏi về mô hình OSI mạng bảy lớp (lớp vật lý, lớp liên kết dữ liệu). , lớp mạng, lớp vận chuyển, lớp phiên). Hơn nữa, một số người sẽ hỏi giao thức IP (lớp mạng) / TCP (lớp vận chuyển) nằm ở lớp nào. giao thức IP dựa trên các liên kết và TCP dựa trên các vấn đề liên quan đến đầu cuối. Thực ra những câu hỏi này không phức tạp nhưng một khi không đọc thì bạn sẽ quên. Nếu gần đây tôi không đọc những cuốn sách liên quan, tôi chỉ có thể lắc đầu khi được hỏi về chúng. Nhìn xem, ở đây bạn cũng có thể nhận được một số câu trả lời phỏng vấn. Nếu nó hữu ích với bạn, hãy cho nó một lượt thích (đùa thôi, bạn không thích cũng không sao).
Là một trong những lõi có tính tương tranh cao, mô-đun mạng là cốt lõi của đồng bằng. Trên thực tế, việc triển khai plain1.1 dựa trên chế độ Lò phản ứng. Khung mạng không nên xem xét và can thiệp quá nhiều vào các tình huống tiêu dùng của người dùng. Trong trường hợp này, độ phức tạp trong thiết kế của nó. mô-đun mạng sẽ bị giảm đi rất nhiều. Gần đây, sau khi đọc thư viện mã nguồn mở muduo của Chen Shuo, tôi đã biết về một chế độ có tên là một vòng lặp trên mỗi luồng. Chế độ này tính đến hiệu suất đồng thời và độ an toàn của luồng. Tôi nghĩ chế độ này có thể được sử dụng để chuyển đổi mô-đun mạng và nhật ký không đồng bộ (. Việc triển khai AsyncLogger gần như đề cập đến việc triển khai thư viện nguồn mở này. Tôi nghĩ rằng một số tối ưu hóa có thể được thực hiện sau này nhờ các tiêu chuẩn mới nên sẽ có nhiều cách hơn để cải thiện hiệu suất.
Lập trình đồng thời là một khó khăn mà C++ và các ngôn ngữ khác gặp phải. Tất nhiên, cũng có một loại khóa. Triển khai miễn phí, nhưng vẫn còn tương đối nhiều khóa được sử dụng trong quá trình phát triển. Khi nói đến khóa, có thể có mutex (khóa mutex), rwlock (khóa đọc/ghi chia sẻ/khóa độc quyền), spinlock (khóa quay), trong muduo này. Ý kiến của Chen Shuo trong khung nguồn mở mạng là sử dụng mutex là đủ và hiệu suất của nó không tệ. Tôi cũng đồng ý với quan điểm này, std::mutex là một phần của tiêu chuẩn C++ và các khóa khác thì không. Khi Chen Shuo xử lý các khóa trong muduo, anh ấy sử dụng bản sao trên ghi để thu nhỏ phần quan trọng. Điều này mang lại sự đảm bảo chắc chắn cho việc cải thiện tính tương tranh và bảo mật. Tôi nghĩ ý tưởng này thực sự xuất phát từ Mục 29 "C++ hiệu quả": Để phấn đấu cho ngoại lệ. -safe code, Scott Meyers cung cấp một cách triển khai an toàn ngoại lệ mạnh mẽ ở đây, đó là sao chép và trao đổi. Nếu quan tâm, bạn có thể đọc các chương cụ thể.
Khi đạt được tốc độ, hãy cố gắng che giấu các chi tiết phức tạp, nghĩa là không truyền bá sự phức tạp cho người dùng, người dùng chỉ cần quan tâm đến việc xử lý các phép tính logic. Đây là điều mà Yunfeng đã nói khi thiết kế Skynet. gói đến và sau đó trả lại tin nhắn tùy theo tình huống.
Thứ hai, lớp dưới cùng cần tăng tốc độ hiệu quả của hoạt động chương trình về mặt triển khai. Ngoài đa luồng, còn để giảm chi phí chạy, tôi nghĩ có hai điểm quan trọng: thời gian biên dịch (một số). một số tính toán nhất định nên được đặt càng nhiều càng tốt.
thời gian tuân thủ: Trong quá trình biên dịch, nếu phép tính được đặt trong trình biên dịch thì không cần phải chịu thêm chi phí để tính toán trong thời gian chạy. Cách tiếp cận này thường được sử dụng trong TMP (Lập trình meta mẫu) và Lập trình chung (lập trình chung). Ví dụ: trong cuộc phỏng vấn, cách tìm tổng của tất cả các số từ 1 đến N. Không thể sử dụng phép nhân, chia và for. while, if, else, switch, case và toán tử ba ngôi?:, hãy xem có rất nhiều hạn chế ở đây, liệu đệ quy thông thường có thể giải quyết được vấn đề này không? Câu trả lời là đệ quy thông thường yêu cầu các câu lệnh và toán tử có điều kiện nêu trên và không thể sử dụng được. Chà, câu hỏi này thực sự có thể được giải quyết từ một số khía cạnh, chẳng hạn như sử dụng hàm tạo và biến tĩnh của các lớp, sử dụng hàm ảo và sử dụng con trỏ hàm. Một số người sẽ biết những điều này nếu họ đã đọc đề nghị của Jianzhi. Đã xem. Ngoài ra còn có một giải pháp phổ biến hơn, đó là sử dụng các mẫu. Chúng ta hãy xem mã của giải pháp này (tôi đặt nó ở đây vì nó ngắn):
mẫu
số nguyên
Không>
lớp học
CalcNum {
công cộng
:
liệt kê
{n = Số Calc
1
>
::n + N }; }; mẫu
<>
lớp học
Tính số<
1
>
{
công cộng
:
liệt kê
{n =
1
}; };
số nguyên
chính() { std::cout
<<
"
N:
"
<< Tính số<
100
>().n <<
std::endl; }
Bạn đọc đúng đấy, giá trị của n không được tính trong thời gian chạy mà được tính toán đệ quy khi trình biên dịch triển khai mẫu, tức là việc tính toán xảy ra tại thời điểm biên dịch. Nếu số lượng N lớn hơn thì sẽ tốn nhiều chi phí hơn. thời gian sẽ tăng lên, điều này được phản ánh qua thời gian biên dịch dài hơn, nhưng không tiêu tốn tính toán trong thời gian chạy. Nhờ từ khóa constexpr được thêm vào sau C++11, đặc biệt là sau sự cải tiến của C++14, ngày càng có nhiều thứ có thể được tính toán trong quá trình biên dịch và ngày càng có nhiều giao diện trong thư viện chuẩn là constexpr. xây dựng Tiêu chuẩn mọi người và ngành công nghiệp đồng ý rằng lập trình thời gian biên dịch đáng được xem xét.
Thuật toán: Toán học là một trong những trí tuệ vĩ đại của nhân loại. Các thuật toán do toán học tạo ra có thể giải quyết nhiều vấn đề trong cuộc sống bao gồm xác suất, tài chính, v.v. Thuật toán có thể được sử dụng để giải quyết nhiều vấn đề khó khăn, thường với chi phí rất thấp. . Ngày nay, AI (trí tuệ nhân tạo) một lần nữa được đẩy lên hàng đầu, các vị trí tương ứng với thuật toán trở nên rất hot. Những người mới ra trường có thể được trả lương cao hơn những người đã làm trong các chương trình hơn chục năm. Làm sao điều này có thể không đáng ghen tị? Nhưng có những ngưỡng cho các thuật toán, đặc biệt đối với một số thuật toán nâng cao, bạn cần có một nền tảng toán học rất vững chắc. Tôi xin lỗi vì tôi hơi thiếu sót về toán học. Mặc dù ở nhà tôi vẫn có tài liệu tham khảo nhanh về thuật toán hàm C/C++. Tôi không biết nhiều về các thuật toán. Tôi thấy các thuật toán gần đây được cung cấp bởi Jianzhi. Tôi cảm thấy chúng không chỉ dành cho các cuộc phỏng vấn mà còn giúp tôi cải thiện và nâng cao các kỹ năng của mình. quan tâm đến họ. Bạn bè có thể muốn tìm hiểu.
Lý do tại sao thuật toán có thể tăng tốc thời gian chạy sẽ rõ ràng với mọi người nếu tôi cho bạn một hoặc hai ví dụ, chẳng hạn như một câu hỏi phỏng vấn cổ điển mà tôi đã không trả lời chính xác trong cuộc phỏng vấn qua điện thoại với NetEase vào năm 2013. Lý do là rằng tôi không có kiến thức gì về lĩnh vực này cả. Vì tôi chưa đọc nên chỉ có thể đặt câu hỏi và không biết. Câu hỏi này là làm thế nào để xóa một nút trong danh sách liên kết một chiều trong thời gian O(1). Nếu bạn không tiếp xúc được với kiến thức liên quan, trừ khi bạn có kỹ năng toán học tốt và rất quen thuộc với cấu trúc dữ liệu danh sách liên kết. thật khó để trả lời câu hỏi này. Thực ra, câu hỏi này không hề phức tạp, nó đơn giản hơn rất nhiều so với những bài toán có thể giải quyết bằng cách sử dụng các công thức đó. Điều đầu tiên là bạn cần phải làm quen với cấu trúc dữ liệu của danh sách liên kết. Danh sách liên kết một chiều có nghĩa là mỗi nút có một con trỏ tới nút tiếp theo và con trỏ tới nút tiếp theo của nút ở cuối danh sách liên kết trống. Với sự hiểu biết về cấu trúc dữ liệu của danh sách liên kết và một chút suy nghĩ khác biệt, việc xóa một nút có nghĩa là loại bỏ nút đó khỏi danh sách liên kết. Theo truyền thống, điều có thể nghĩ đến là duyệt qua danh sách liên kết cho đến khi nút đó trỏ đến con trỏ tiếp theo. của con trỏ trước đó. Nếu bạn cần xóa con trỏ tiếp theo của con trỏ, việc này sẽ mất O(n) thời gian và hiệu quả về thời gian không thể đáp ứng được yêu cầu của câu hỏi. Sau đó, bằng cách sử dụng tư duy khác biệt, chúng ta cũng có thể sử dụng kỹ thuật thay thế để trao đổi dữ liệu của chính chúng ta và nút tiếp theo, sau đó để nút bị xóa trỏ đến nút tiếp theo của nút tiếp theo. Khi đó, hiệu quả về thời gian của thao tác này là. O(1). Tất nhiên, để làm cho mã trở nên mạnh mẽ, bạn cần xem xét rằng nút nằm ở nút đầu và nút đuôi. Mã như sau:
vô hiệu
del_list_node(list_node_t** đầu, list_node_t*
nút) {
nếu như
(!đầu || !nút)
trở lại
;
nếu như
(nút->
tiếp theo) { tự động tiếp theo
= nút->
tiếp theo; nút
->giá trị = nút->
giá trị; nút
->tiếp theo = tiếp theo->
Kế tiếp;
delete
tiếp theo; tiếp theo
=
nullptr; }
khác
nếu như
(*đầu ==
nút) {
*đầu =
giá trị rỗng;
delete
nút; nút
=
nullptr; }
khác
{ nhiệt độ tự động
= *
cái đầu;
trong khi
(tạm thời && tạm thời->
tiếp theo) { tạm thời
= tạm thời->
Kế tiếp; }
nếu như
(!temp || temp != nút)
trở lại
; nhiệt độ
->tiếp theo =
giá trị rỗng;
delete
nút; nút
=
giá trị rỗng; } }
Về ứng dụng của thuật toán này, khi đọc mã nguồn của muduo, tôi thấy một phương pháp trao đổi nút cần xóa và nút đuôi trong danh sách rồi xóa nút đuôi. Kỹ thuật này giúp giảm mức tiêu thụ truyền tải và cải thiện. hiệu quả hoạt động của chương trình.
Về mã tương ứng của thuật toán, bạn có thể tìm thấy nó trong kho lưu trữ này cũng có các ví dụ về một số tính năng mới của C++ (tôi sẽ tải chúng lên sau khi sắp xếp chúng): https://github.com/viticm/cpp_misc.
3. Thiết kế
Phần này thực sự được thực hiện vì mục đích đơn giản và nhanh chóng, đó là chọn một hoặc hai mẫu thiết kế. Tôi dự định sử dụng phương thức impl và std::function để triển khai chế độ Chiến lược trong plain2.0. đoạn mã sau đầu tiên:
#bao gồm
"
plain/cơ bản/config.h
"
#bao gồm
không gian tên
đơn giản {
lớp học
PLAIN_API AsyncLogger: không thể sao chép {
công cộng
: Trình ghi nhật ký không đồng bộ(
hằng số
tiêu chuẩn::
sợi dây
&
tên, std::size_t roll_size, int32_t flush_interval
=
3
);
~
Trình ghi nhật ký không đồng bộ();
công cộng
:
vô hiệu
thêm vào(
hằng số
std::string_view&
nhật ký);
vô hiệu
bắt đầu();
vô hiệu
dừng lại();
riêng tư
:
cấu trúc
Triển khai; std::unique_ptr
impl_; }; }
//
không gian tên đơn giản
|
Ban đầu tôi muốn lấy logger.h làm ví dụ, nhưng cái đó có nhiều nội dung và tôi sợ mọi người sẽ phản cảm sau khi đọc nó nên tôi đã chọn một câu nói đơn giản ở đây. và làm mới? Cá nhân tôi nghĩ là như vậy và giao diện rõ ràng trong nháy mắt. Các chi tiết triển khai được ẩn đi nhờ phương pháp Impl. Đối với việc triển khai Chiến lược, trên thực tế, các vấn đề liên quan đến mạng phía sau 1.1 đã được thực hiện, nhưng công việc chưa đủ kỹ lưỡng và vẫn còn một số vấn đề về đóng gói đa hình. Tôi sẽ giải thích chi tiết cách triển khai cụ thể sau về mặt thiết kế mạng. Nếu quan tâm, bạn có thể chú ý đến các bài viết sau.
4. Tương thích
Khả năng tương thích ở đây không chỉ là khả năng tương thích của ABI nâng cấp mà còn là khả năng tương thích đa nền tảng.
plain là một thư viện mạng đa nền tảng và có những lý do lịch sử cho điều này, bởi vì ứng dụng khách của triển khai ban đầu này chạy trên Windows và các trò chơi chạy trên PC của Microsoft thường được gọi là trò chơi máy khách, vì vậy trong plain1rc có hỗ trợ đa nền tảng. cho linux và windows. Ở plain 2.0, tôi định thêm một nền tảng mới, đó là MAC. Trước đây, khi chưa có MAC, tôi không muốn bận tâm đến nền tảng này, nhưng bây giờ có rồi, tôi sẽ đơn giản lấy. nó vào xem xét. Do đó, ba macro được xác định trong tệp định nghĩa macro đa nền tảng bao gồm/plain/basic/macros/platform.h: OS_UNIX (nền tảng giống LINUX), OS_WIN (Microsoft PC), OS_MAC (Apple PC).
Để đạt được đa nền tảng tốt hơn, giải pháp của tôi là sử dụng thư viện tiêu chuẩn càng nhiều càng tốt. Giống như Chen Shuo đã nói, hãy giao công việc bẩn thỉu và mệt mỏi cho người khác, còn những người khác ở đây là ban tổ chức xây dựng tiêu chuẩn ( của người biên soạn Tác giả bày tỏ sự không hài lòng). Trừ khi bạn muốn triển khai một số chức năng không có trong thư viện chuẩn, chẳng hạn như epoll, một giao diện có thuộc tính nền tảng, bạn sẽ thực hiện một số xử lý liên quan đến nền tảng. Thành thật mà nói, đây thực sự là một công việc mệt mỏi. Điểm thứ hai là giảm thiểu sự phụ thuộc. Ví dụ, tôi không sử dụng thư viện boost do những người (người thông minh) do ủy ban tiêu chuẩn chỉ định. Thư viện boost có nhiều thứ có hiệu suất cao, và cũng có một số thứ có hiệu suất cao. sắp bước vào thư viện chuẩn. Thật vậy, Có nhu cầu học, Scott Meyers trong "C++ hiệu quả" Mục 55: Làm quen với Boost. Bạn nên làm quen với thư viện này. Tôi đã nghĩ rằng nếu thư viện này được sử dụng, tại sao tôi không sử dụng asio thay vì phải tự mình triển khai thư viện mạng một cách rầm rộ? Và với một phần phụ thuộc nữa, người dùng chắc chắn sẽ cần phải cài đặt nó. Thành thật mà nói, tôi không thích khả năng tăng tốc quá lớn trừ khi có một công cụ quản lý gói triển khai golang, sau khi tôi khai báo phần phụ thuộc trong mã. việc khởi tạo có thể giúp tôi tự động chỉ cài đặt những mô-đun tôi cần, trong trường hợp này tôi nghĩ nên sử dụng nó.
Để đạt được khả năng tương thích ABI, tôi sẽ loại bỏ thiết kế chức năng ảo khỏi hầu hết các giao diện và sử dụng phương pháp thiết kế Pimpl (Triển khai con trỏ). Tôi sẽ cố gắng ẩn những phần mà người dùng không nhìn thấy được. Ngoài ra, đối với người dùng, không cần phải viết lại các lớp mà chỉ cần thiết lập các phương thức xử lý mà họ cần quan tâm. Đây chính xác là chế độ Chiến lược được triển khai bằng std::function.
。
5. Kiểm tra và ví dụ
Không có thử nghiệm đơn vị nào ở phiên bản 1.0 thuần túy, nhưng nó chỉ khả dụng khi phiên bản đạt 1.1. Nếu không có thử nghiệm đơn vị, tôi chỉ có thể dựa vào một ví dụ đơn giản để tìm ra sơ hở trong mã. Thành thật mà nói, mỗi lần như vậy tôi hơi mệt mỏi. Tôi đã gỡ lỗi nó. Do đó, đối với các mô-đun tôi đã viết sau này, chẳng hạn như sau khi xem mô-đun ORM (Ánh xạ quan hệ đối tượng) của laravel, một khung PHP, tôi thấy một số lượng lớn các bài kiểm tra đơn vị trong đó, vì vậy tôi đã bắt chước cách triển khai của nó và viết mô-đun tương ứng bằng C++ và đặt nó ở dạng đơn giản, trong thư mục db https://github.com/viticm/plain/tree/master/framework/core/src/db , mô-đun này sẽ được đơn giản hóa trong phiên bản 2.0 và việc triển khai ORM sẽ được tạo thành một dự án riêng hoặc đưa vào một trình cắm thêm để sử dụng. Nói về điều này, tôi hơi lạc đề. Điều tôi muốn nói là thử nghiệm đơn vị mới chỉ bắt đầu được sử dụng ở đây. Bạn có thể thấy rằng các thử nghiệm bên trong vẫn chưa hoàn thiện. github.com/viticm/plain/tree/master/framework/unit_tests/core_test. Vì 2.0 thực sự là một sự chuyển đổi lớn nên có thể triển khai các trường hợp thử nghiệm đơn vị âm thanh để kiểm tra một chút độ mạnh của chương trình. Tuy nhiên, tôi nghĩ rằng tôi chưa thực hiện loại thử nghiệm hồi quy tự động nào có thể được sử dụng lại. đầu tiên Chỉ cần thực hiện một thử nghiệm truyền thống và bạn có thể bổ sung thêm sau nếu cần thiết và khi bạn có thời gian. Phần đó chỉ là thêm các viên gạch.
Đối với các ví dụ, do lười biếng, chỉ có một ứng dụng đơn giản trong 2.0, tôi dự định triển khai các ví dụ máy chủ sau hoặc nhiều hơn: echo, loại bỏ, trò chuyện, v.v. Điều này có thể kiểm tra khả năng tương tranh của đồng bằng khi được sử dụng làm máy chủ, tương tự như kiểm tra hiệu suất trong sự kiện tự do. Tất nhiên, dữ liệu đang chạy có thể được so sánh một chút và điều này có thể được thực hiện như một điều gì đó khiến bạn cảm thấy thành tựu (lừa dối thủ công, khoe khoang và lừa dối chính mình).
tiêu chuẩn
C++23(2023)
1. Mệnh đề sai
C++23 có thực sự được phát hành không?
Có vẻ như C++23 vẫn chưa được phát hành chính thức nhưng các tính năng mới được ban tổ chức phê duyệt đã bị đóng băng. Trên thực tế, có thể coi là C++23 đã được phát hành và các tệp tiêu đề và tính năng mới. đã được hoàn thiện. Nhưng có một vấn đề ở đây, đó là các trình biên dịch chính thống GCC (hiện là phiên bản mới nhất 12.1) và VS (Microsoft Visual Studio) thực tế không hỗ trợ nhiều tính năng của C++23, tức là các tác giả trình biên dịch vẫn đang điền vào những Cạm bẫy, nhưng tôi nghĩ C++23 không quá cấp bách. Trước tiên hãy triển khai chức năng std::format của C++20, nếu không nhiều người sẽ phải đối mặt với C printf đầy rẫy những cuộc thảo luận và chỉ trích. Nói cách khác, tiêu chuẩn C++ hiện tại được hỗ trợ đầy đủ hơn là C++17. Tất cả các chức năng của C++17 đều có sẵn, nhưng cũng có thể sử dụng nhiều chức năng của C++20.
Từ những điều trên, không khó để thấy rằng những gì tôi nói ở đây về việc sử dụng C++23 rõ ràng là một đề xuất sai, bởi vì các tính năng của C++23 không được hỗ trợ. Làm cách nào tôi có thể viết một thư viện dựa trên C++23? Lý do tại sao tôi đặt ra tiêu chuẩn ở đây là để nhắc nhở bản thân rằng đơn giản là dựa trên tiêu chuẩn C++ mới nhất. Đây thực sự là một nỗ lực. Tôi nghĩ cần phải cố gắng. Một người không cần phải ngủ quên trên chiến thắng của mình. Việc thử một điều gì đó mới mẻ là rất hữu ích. Về vấn đề này, tôi tin rằng chỉ những người tích cực đón nhận tương lai mới được tương lai đón nhận. Do đó, sinh viên và những người bạn khác muốn học C++ có thể muốn bắt đầu học với các tiêu chuẩn mới nhất, bởi vì trong mười năm nữa bạn sẽ thấy rằng những công nghệ này sẽ thực sự trở nên phổ biến.
2、mô-đun
C++20 đã giới thiệu các mô-đun, một tính năng đã được các ngôn ngữ khác như python và javascript giới thiệu. Thực sự là hơi muộn vào thời điểm này. Thành thật mà nói, không có cách nào để làm điều này, vì vậy những người thiết kế ngôn ngữ C++ đã bắt đầu bằng
C với hướng đối tượng (C và hướng đối tượng), nghĩa là C++ là một dẫn xuất của C, và tệp tiêu đề và cách triển khai C ban đầu là riêng biệt. Nếu bạn giới thiệu điều này sớm hơn, bạn sẽ thấy rằng sự khác biệt giữa C++ và C thực sự lớn. Tôi đoán Điều này sẽ gây ra một số khó chịu đối với những người hâm mộ trung thành của C (dù sao thì C vẫn là anh lớn và nhiều ngôn ngữ cấp cao hầu như luôn được triển khai bằng ngôn ngữ C).
Điều đáng tiếc là trình biên dịch trong C++20 không cung cấp thư viện chuẩn có thể sử dụng được, chẳng hạn như các câu lệnh
nhập std; Trên thực tế, tiêu chuẩn C++23 yêu cầu phải có thư viện tiêu chuẩn hỗ trợ, vì vậy việc này vẫn đòi hỏi nỗ lực của trình biên dịch. Thành thật mà nói, bạn đang thực sự làm việc chăm chỉ vì lợi ích của mọi người. nên làm việc chăm chỉ hơn. Ngoài ra còn có một điểm khó khăn trong việc sử dụng các mô-đun, đó là thứ tự biên dịch các tham chiếu lẫn nhau giữa các mô-đun. Cuối cùng, nó cần phải được biên dịch.
*.gcm Chỉ khi đó bạn mới có thể sử dụng tính năng nhập. Do tính phức tạp nên hiện tại, plain không xem xét sử dụng các mô-đun.
Do tính hấp dẫn của các tính năng mô-đun, cá nhân tôi nghĩ rằng các mô-đun vẫn nên được hỗ trợ trong tương lai, đặc biệt đối với các nhà phát triển thư viện. Đây thực sự là một công cụ tuyệt vời.
Linh tinh
viết ở cuối
1. Vườn
Vô tình, tôi đã ở blog hơn mười năm. Tóm lại, mười năm qua thế giới đã thay đổi rất nhiều, đặc biệt là blog bên cạnh có rất nhiều hạn chế, chẳng hạn như bạn cần phải đăng nhập để xem. copy.Đăng nhập, mặc dù tôi hiểu cách làm đó là để thu hút nhiều người dùng hơn nhưng thành thật mà nói, nó khiến mọi người hơi khó chịu. Nhưng khu vườn khiến tôi cảm thấy rất sảng khoái, mặc dù rõ ràng tôi cảm thấy khu vườn quả thực đã trở nên hơi vắng vẻ, và lượng đọc sách cũng giảm đi một chút. Nhưng tôi nghĩ rằng với tư cách là nơi chia sẻ công nghệ thuần túy, kiểu vườn này rất đáng được khen ngợi. Tôi mong rằng khu vườn có thể tồn tại và ngày càng tốt hơn. Làm vườn mình cũng học được rất nhiều kiến thức qua một số bài viết nên rất vui được chia sẻ kiến thức của mình, mong rằng kiến thức này có thể giúp ích được cho mọi người.
Nhiều năm trước, khi nguồn đóng còn rất phổ biến, người ta sẽ không nghĩ rằng nguồn mở ngày nay lại phổ biến đến thế. Nếu con người muốn phát triển thì tôi nghĩ trước hết chúng ta phải có tinh thần chia sẻ này. để chia sẻ, nó sẽ tương đương với việc đóng cửa đất nước, trừ khi bạn Nếu công nghệ cần được giữ bí mật, bạn có thể cho chúng tôi biết cách khác. Chia sẻ kỹ năng và ý tưởng của riêng bạn cũng có thể mang lại cho bạn hạnh phúc.
2. Sách được đề xuất
"Tư duy lập trình C++": Nó có thể cung cấp cho bạn sự hiểu biết toàn diện về tất cả các khía cạnh của thiết kế ngôn ngữ C++.
"C++ Primer Plus Fifth Edition": Bạn có thể chọn cuốn sách này cho người mới bắt đầu.
"Effective C++ Third Edition": Lập trình C++ hiệu quả, xem cách các chuyên gia sử dụng một số kỹ thuật (tổng cộng 55 mục) để viết.
"C++ hiện đại hiệu quả": Tác giả của cuốn sách tương tự như trên là Scott Meyers, nhưng nó cung cấp một số giới thiệu về C++11/14, cũng như tóm tắt một số tính năng. Nó cũng có các gợi ý dựa trên mệnh đề (42 mục. ) .
"C++20 Advanced Programming Fifth Edition": Phiên bản tiếng Trung được phát hành vào cuối năm ngoái. Bây giờ tôi đang đọc phiên bản tiếng Anh. Không có cách nào để làm quen với C++20. Tôi chỉ có thể dựa vào đó. Tiếng Anh dồn nén đọc lâu rồi, đọc xong thấy tiếng Anh không thành vấn đề (có một loại tiếng Trung cổ điển mà người xưa đọc lâu sẽ trở thành ảo tưởng). thời gian). Cuốn sách này đánh dấu rõ ràng các tính năng mới của C++20.
"Lập trình nâng cao trong môi trường UNIX": Nếu bạn phát triển mạng POSIX, bạn cần biết về cuốn sách này. Đây dường như được gọi là "Kinh thánh" về lập trình UNIX. Nó giới thiệu chi tiết về hệ điều hành. (Coi như không xem).
"Giải thích chi tiết TPC/IP Tập 1": Nhiều người khuyên bạn nên đọc cuốn sách này. Nếu bạn muốn hiểu tất cả các khía cạnh của lập trình mạng thì nên đọc cuốn sách này.
"Giới thiệu về thuật toán": Nếu bạn muốn hiểu sâu hơn về thuật toán thì cuốn sách này rất phù hợp.
3. Trang web
github: https://github.com/ Nó nên được coi là cộng đồng nguồn mở lớn nhất.
cppreference: https://en.cppreference.com/ Nếu bạn muốn biết về các tính năng mới của C++23, trang web này tương đối toàn diện. Bạn cũng có thể xem các giao diện của thư viện chuẩn và các ví dụ tương ứng.
coding-interview-university: https://github.com/jwasham/coding-interview-university Nếu bạn muốn vào các công ty hàng đầu như Google và Microsoft thì đây là kinh nghiệm được một người bạn nước ngoài chia sẻ về cách học có hệ thống. Tôi không thể xử lý tất cả các khía cạnh của cuộc phỏng vấn và phỏng vấn, vì vậy tôi phải dựa vào tất cả bạn bè của mình ở Houlang.
QQ: 348477824 (nhóm giao tiếp đơn giản). Nhóm này hiện đã chết như hình đại diện, nhưng điều đó không ngăn cản những người bạn mới tham gia vào một số cuộc thảo luận kỹ thuật. Tất nhiên, nếu ai đó có thể cung cấp một cách rõ ràng. biểu tượng, Không thể tuyệt vời hơn.
。
Cuối cùng, bài viết này về việc đánh giá về đường tái thiết khung mạng plain2.0 (c++23withoutmodule) kết thúc tại đây. Nếu bạn muốn biết thêm về đường tái thiết khung mạng plain2.0 (c++23withoutmodule) thì hãy xem nội dung đánh giá. , vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!