Best practices
-
Sử dụng
constkhi có thểKhi một biến, tham chiếu, hoặc con trỏ không cần thay đổi giá trị sau khi khởi tạo, hãy khai báo nó với từ khóa
const. Điều này giúp ngăn chặn các thay đổi ngoài ý muốn và làm mã dễ hiểu hơn.const int MAX_SIZE = 100;
void printName(const std::string &name); -
Sử dụng auto cho kiểu suy diễn tự động
autogiúp bạn tránh phải lặp lại các kiểu dài, đặc biệt khi các kiểu đó đã rõ ràng từ ngữ cảnh. Tuy nhiên, không lạm dụngautonếu nó làm mã khó đọc.auto it = myMap.begin(); // Tự động suy diễn kiểu của it -
Sử dụng
smart pointersthay vì con trỏ thô (raw pointers)std::shared_ptr,std::unique_ptr, vàstd::weak_ptrgiúp quản lý bộ nhớ tự động và ngăn ngừa rò rỉ bộ nhớ. Hạn chế sử dụng con trỏ thô trừ khi thật sự cần thiết.std::unique_ptr<int> ptr = std::make_unique<int>(10); -
Sử dụng range-based for loop cho các containers
Vòng lặp
range-basedgiúp mã ngắn gọn hơn và dễ đọc khi duyệt qua các phần tử của container.std::vector<int> numbers = {1, 2, 3};
for (const auto &num : numbers) {
std::cout << num << std::endl;
} -
Khai báo biến gần với nơi sử dụng
Khai báo biến chậm nhất có thể, ngay khi bạn cần đến nó để làm mã rõ ràng hơn. Tránh khai báo tất cả biến ở đầu hàm trừ khi cần thiết.
-
Sử dụng enum class thay vì enum
enum classgiúp tránh xung đột tên và tăng tính an toàn vì các giá trịenum classkhông thể chuyển đổi ngầm định sang kiểu nguyên.enum class Color { Red, Green, Blue };
Color color = Color::Red; -
Sử dụng nullptr thay vì NULL hoặc 0
nullptrlà con trỏ rỗng mới trong C++11, an toàn hơn và làm mã dễ hiểu hơn. -
Tránh sử dụng macro trừ khi thật sự cần thiết
Macro có thể làm mã khó hiểu và khó bảo trì, đặc biệt khi thay thế bằng hằng
constexpr,consthoặcinlinelà hợp lý hơn.constexpr int MAX_SIZE = 100; -
Tránh dùng quá nhiều
inlineinlinenên dùng cho các hàm nhỏ, thường là những hàm được định nghĩa ngay trong lớp. Tránh đánh dấu các hàm lớninlinevì chúng có thể làm mã tăng kích thước không cần thiết. -
Chia nhỏ hàm và giữ mỗi hàm làm một việc duy nhất
Mỗi hàm nên làm một công việc nhất định và được đặt tên mô tả rõ ràng công việc đó. Tránh viết các hàm quá dài hoặc đa nhiệm.
-
Sử dụng
std::arrayvàstd::vectorthay vì mảng C-stylestd::arrayvàstd::vectoran toàn hơn mảng C-style vì chúng tự động quản lý kích thước và các vấn đề biên. -
Sử dụng
std::movevàstd::forwardđể tối ưu hiệu suấtstd::movevàstd::forwardgiúp di chuyển dữ liệu thay vì sao chép nó, tối ưu hóa hiệu suất khi làm việc với các đối tượng lớn hoặc các tài nguyên không sao chép được. -
Tránh copy không cần thiết với tham chiếu const trong hàm
Nếu một tham số là đối tượng lớn và không cần thay đổi, hãy truyền nó dưới dạng tham chiếu
const &để tránh việc sao chép không cần thiết.void processData(const std::vector<int> &data); -
Cẩn trọng khi sử dụng
using namespaceTránh sử dụng
using namespace std;trong các file header hoặc file lớn vì nó có thể gây ra xung đột tên. Thay vào đó, khai báo cụ thể tên cần dùng hoặc sử dụng namespace trong một phạm vi hẹp. -
Sử dụng std::optional cho các giá trị có thể không tồn tại
std::optionalgiúp đại diện cho các giá trị có thể trống hoặc không xác định, làm mã rõ ràng hơn thay vì sử dụng các giá trị đặc biệt (như -1) để chỉ trạng thái trống. -
Sử dụng
std::chronocho thời gian và thời lượngThư viện
<chrono>cung cấp các kiểu dữ liệu an toàn và mạnh mẽ cho thời gian và thời lượng, thay vì sử dụnginthoặcfloat. -
Giải phóng tài nguyên bằng RAII (Resource Acquisition Is Initialization)
RAII giúp quản lý tài nguyên (bộ nhớ, file, mutex,...) bằng cách gán chúng vào các đối tượng có vòng đời tự động. Khi đối tượng ra khỏi phạm vi, tài nguyên sẽ tự động được giải phóng.
-
Viết tài liệu và bình luận một cách hợp lý
Bình luận mã để giải thích ý định của bạn, đặc biệt khi mã phức tạp hoặc khó hiểu. Sử dụng tài liệu rõ ràng cho các hàm, lớp, và các tham số của chúng.
-
Tuân thủ các quy ước đặt tên nhất quán
Giữ một phong cách đặt tên nhất quán giúp mã dễ đọc và dễ bảo trì hơn. Ví dụ, có thể sử dụng
camelCasecho tên biến và hàm,PascalCasecho tên lớp. -
Sử dụng các công cụ phân tích mã và kiểm tra bộ nhớ
Các công cụ như
valgrind,AddressSanitizer, vàClang-Tidygiúp phát hiện sớm lỗi bộ nhớ và các vấn đề tiềm ẩn. -
Viết unit test cho các đoạn mã quan trọng
Unit testing giúp bạn kiểm tra các hàm và lớp riêng lẻ, đảm bảo rằng chúng hoạt động như mong đợi và giúp phát hiện lỗi sớm.
-
Quản lý ngoại lệ
- Throw exceptions for error handling: Sử dụng ngoại lệ để xử lý lỗi thay vì sử dụng mã lỗi cổ điển.
- Noexcept specification: Sử dụng
noexceptđể xác định các hàm không ném ra ngoại lệ.
-
Tối ưu hóa hiệu suất
- Profile and optimize: Sử dụng công cụ profiling để xác định các điểm yếu trong mã của bạn và tối ưu hóa chúng.
- Avoid premature optimization: Không nên tối ưu hóa quá sớm trước khi bạn biết rằng đó là điểm yếu thực sự.