Best practices
-
Sử dụng
const
khi 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
auto
giú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ụngauto
nế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 pointers
thay vì con trỏ thô (raw pointers)std::shared_ptr
,std::unique_ptr
, vàstd::weak_ptr
giú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-based
giú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 class
giúp tránh xung đột tên và tăng tính an toàn vì các giá trịenum class
khô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
nullptr
là 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
,const
hoặcinline
là hợp lý hơn.constexpr int MAX_SIZE = 100;
-
Tránh dùng quá nhiều
inline
inline
nê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ớninline
vì 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::array
vàstd::vector
thay vì mảng C-stylestd::array
vàstd::vector
an 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::move
vàstd::forward
để tối ưu hiệu suấtstd::move
vàstd::forward
giú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 namespace
Trá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::optional
giú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::chrono
cho 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ụngint
hoặ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, v.v.) 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
camelCase
cho tên biến và hàm,PascalCase
cho 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-Tidy
giú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ự.