- C++ khác C ở những điểm nào quan trọng nhất?
C++ mở rộng C với: - OOP: class, kế thừa, đa hình, encapsulation. - Tham chiếu (&): alias an toàn hơn con trỏ raw. - new/delete thay malloc/free — gọi constructor/destructor. - Templates: code generic type-safe. - Ngoại lệ (try/catch): thay if-else kiểm tra lỗi…
- Tham chiếu (`&`) trong C++ là gì? Khác con trỏ thế nào?
Tham chiếu là alias của một biến đã tồn tại — cùng địa chỉ, cùng giá trị, khác tên gọi. Khác con trỏ: Tham chiếu Con trỏ --------- Null Không được null Có thể null Reassign Không đổi được target Có thể Cú pháp dùng…
- `new` và `malloc` khác nhau thế nào?
new malloc --------- Loại toán tử C++ hàm C Constructor Có, gọi tự động Không gọi Kiểu trả về typed pointer void Khi thất bại throw std::badalloc trả nullptr Giải phóng delete / delete[] free() Không trộn lẫn: new phải delete, malloc phải free. Trong…
- Stack và Heap trong C++ khác nhau thế nào?
Stack: vùng nhớ tĩnh, cấp phát tự động khi hàm được gọi, giải phóng khi hàm trả về. Truy cập nhanh, kích thước hạn chế (thường vài MB). Heap: vùng nhớ động, cấp phát qua new/malloc, phải giải phóng thủ công bằng delete/free. Kích thước…
- Inline function là gì? Khi nào nên dùng?
inline gợi ý compiler chèn thân hàm tại điểm gọi thay vì tạo stack frame mới — giảm overhead function call với hàm nhỏ. Khi nên dùng: hàm rất nhỏ (1–3 dòng), được gọi nhiều trong hot path. Khi không nên: hàm lớn — code…
- Function overloading và operator overloading trong C++ là gì?
Function overloading: nhiều hàm cùng tên, khác signature (số/kiểu tham số). Compiler chọn đúng bản tại compile-time. Operator overloading: tái định nghĩa toán tử (+, <<, ==, ...) cho kiểu tự định nghĩa. Khác biệt với overriding: override là ghi đè hàm ở lớp con…
- Dangling pointer là gì? Làm sao tránh?
Dangling pointer là con trỏ trỏ tới vùng nhớ đã bị giải phóng — đọc/ghi vào đó là undefined behavior (crash hoặc corrupt dữ liệu ngầm). Cách tránh tốt hơn: dùng smart pointer (std::uniqueptr, std::sharedptr) — tự giải phóng khi ra scope, không bao giờ…
- RAII trong C++ là gì? Tại sao quan trọng?
RAII (Resource Acquisition Is Initialization): gắn vòng đời tài nguyên (bộ nhớ, file, lock...) vào vòng đời một object trên stack. Cấp tài nguyên trong constructor, giải phóng trong destructor. Khi object ra khỏi scope, destructor tự chạy — tài nguyên được trả lại kể…
- Smart pointer trong C++11: `unique_ptr`, `shared_ptr`, `weak_ptr` khác nhau thế nào?
uniqueptr: sở hữu độc quyền — chỉ có 1 owner, không copy được, chỉ move. Khi ra scope, tự delete. sharedptr: sở hữu chia sẻ — nhiều pointer cùng quản lý 1 object qua reference count. Khi count về 0 thì object bị xoá. weakptr:…
- Shallow copy và deep copy khác nhau thế nào? Khi nào cần deep copy?
Shallow copy (mặc định của compiler): copy từng byte — với member là pointer, cả hai object cùng trỏ về cùng vùng nhớ. Giải phóng một cái → cái kia thành dangling pointer. Deep copy: copy cả nội dung mà pointer trỏ tới — hai…
- `const` với con trỏ: `const int*`, `int* const`, `const int* const` khác nhau thế nào?
Đọc từ phải sang trái: "const" gần nhất áp dụng cho phần tử đứng trước nó. Ví dụ thực tế: Hình dung: const trước = bảo vệ dữ liệu; const sau = bảo vệ địa chỉ.
- 4 tính chất của OOP trong C++ là gì?
1. Encapsulation (Đóng gói): gom data + method vào class; che giấu chi tiết nội bộ qua private/protected. 2. Inheritance (Kế thừa): class con kế thừa thuộc tính/method từ class cha → tái sử dụng code, mở rộng dễ. 3. Polymorphism (Đa hình): cùng interface,…
- Virtual function và pure virtual function khác nhau thế nào?
Virtual function: có cài đặt mặc định ở base class, class con có thể override. Pure virtual function (= 0): không có cài đặt ở base class, class con bắt buộc override. Class chứa pure virtual → abstract class, không thể tạo instance trực tiếp.
- Vtable (virtual table) hoạt động thế nào?
Khi class có ít nhất 1 virtual function, compiler tạo một vtable — mảng các con trỏ hàm cho class đó. Mỗi object có thêm một hidden pointer (vptr) trỏ tới vtable của class thực sự. Khi gọi s-area() (s là Shape trỏ Circle): đọc…
- Diamond problem trong C++ là gì? Giải quyết bằng cách nào?
Diamond problem xảy ra khi class D kế thừa từ B và C, cả hai đều kế thừa từ A. Kết quả: D có 2 bản sao của A, gây nhập nhằng. Giải pháp: virtual inheritance — A chỉ tồn tại 1 lần trong D.…
- Khi nào constructor và destructor được gọi? Thứ tự trong kế thừa?
- STL trong C++ là gì? Gồm những thành phần nào?
STL (Standard Template Library) là thư viện chuẩn C++ cung cấp các cấu trúc dữ liệu và thuật toán đã được tối ưu hoá, dùng qua templates. 3 thành phần chính: 1. Containers: lưu trữ dữ liệu. - Sequence: vector, list, deque, array - Associative:…
- `std::vector` hoạt động thế nào? `size()` và `capacity()` khác nhau thế nào?
std::vector là dynamic array — tự quản lý vùng nhớ liên tục trên heap, tự resize khi cần. - size(): số phần tử hiện có. - capacity(): số phần tử có thể chứa trước khi cần cấp phát lại bộ nhớ. Khi size == capacity…
- `std::map` và `std::unordered_map` khác nhau thế nào? Khi nào chọn cái nào?
std::map std::unorderedmap --------- Cấu trúc nội bộ Red-Black Tree Hash Table Thứ tự key Có thứ tự Không có thứ tự find / insert / erase O(log n) O(1) trung bình, O(n) worst Iterator hợp lệ giữ nguyên sau insert có thể invalid sau rehash…
- Iterator trong STL là gì? Có bao nhiêu loại?
Iterator là object đóng vai trò con trỏ tổng quát để duyệt container — tách algorithm ra khỏi cấu trúc nội bộ của container. 5 loại cổ điển (từ ít đến nhiều khả năng): Loại Đọc Ghi ++ -- [] Ví dụ --------------------- Input Có…
- `std::vector` vs `std::list` — khi nào dùng cái nào?
- Lambda expression trong C++11 là gì? Cú pháp và capture clause hoạt động thế nào?
Lambda là hàm ẩn danh inline, thường dùng cùng STL algorithm. Lưu ý: capture by reference khi lambda tồn tại lâu hơn biến captured → dangling reference. Dùng capture by value hoặc std::sharedptr để an toàn.
- Move semantics và rvalue reference (`&&`) trong C++11 là gì? Tại sao quan trọng?
Trước C++11, truyền object lớn (vector, string) vào hàm luôn copy → tốn kém. Move semantics cho phép "chuyển nhượng" tài nguyên thay vì copy. - lvalue: object có địa chỉ xác định (có thể lấy &). - rvalue: giá trị tạm thời, không có…
- `auto` keyword và range-based for loop trong C++11 dùng như thế nào?
auto: yêu cầu compiler tự suy kiểu (type deduction) từ biểu thức khởi tạo. Range-based for (C++11): Lưu ý: auto& x giữ reference; auto x luôn copy kể cả với reference source.
- `nullptr` trong C++11 khác `NULL` và `0` thế nào?
Trước C++11, NULL thường là macro define NULL 0 — kiểu int, gây nhập nhằng khi overloading. nullptr là literal kiểu std::nullptrt, chuyển đổi ngầm về bất kỳ pointer type nào nhưng không về int. Quy tắc hiện đại: luôn dùng nullptr thay NULL hoặc…
- Rule of Three, Rule of Five trong C++ là gì?
- Template trong C++ là gì? Function template và class template khác nhau thế nào?
- `constexpr` trong C++11/14 là gì? Khác `const` thế nào?
- Structured bindings (C++17) là gì? Cho ví dụ thực tế.
- Undefined behavior (UB) trong C++ là gì? Cho ví dụ thường gặp.
Undefined behavior là hành vi mà chuẩn C++ không quy định kết quả — compiler được phép làm bất cứ điều gì: crash, kết quả sai, hoặc tình cờ "chạy đúng". Ví dụ phổ biến: Tình huống Lý do UB ------ int p = nullptr;…
- Memory leak trong C++ xảy ra khi nào? Cách phát hiện và ngăn chặn?
Memory leak xảy ra khi bộ nhớ được cấp phát bằng new/malloc nhưng không bao giờ được giải phóng — chương trình dần dần ăn hết RAM. Nguyên nhân thường gặp: - Quên delete (đặc biệt khi có exception hoặc early return) - Mất pointer…
- 4 loại type casting trong C++ (`static_cast`, `dynamic_cast`, `reinterpret_cast`, `const_cast`) — mỗi loại dùng khi nào?
Cast Thời điểm Dùng khi --------- staticcast compile-time chuyển đổi an toàn: int→double, upcast, void→T dynamiccast runtime (RTTI) downcast qua hierarchy — trả nullptr/throw nếu sai kiểu reinterpretcast compile-time đọc lại raw bit theo kiểu khác — pointer↔integer, hoàn toàn unsafe constcast compile-time thêm/bỏ const/volatile…
- `explicit` keyword trong C++ dùng để làm gì?
explicit ngăn compiler tự động chuyển đổi ngầm (implicit conversion) khi gọi constructor hoặc toán tử chuyển đổi. Quy tắc thực tế: constructor có 1 tham số nên khai báo explicit trừ khi conversion ngầm đó có ý nghĩa rõ ràng (ví dụ std::string từ…
- Const member function trong C++ là gì? Tại sao cần?
Const member function được khai báo với const sau danh sách tham số — cam kết không thay đổi trạng thái object (không sửa any non-mutable member). Tại sao quan trọng (const-correctness): - Cho phép truyền object bằng const& và vẫn gọi được các getter.…
- `friend` function và `friend` class trong C++ là gì? Khi nào dùng?
friend cho phép một hàm hoặc class truy cập trực tiếp các thành viên private/protected của class khác — phá encapsulation có kiểm soát. Khi dùng hợp lý: - Operator overloading cần truy cập private của cả 2 bên (ví dụ operator<<). - Unit test…
- `static` member trong C++ là gì? Khác member thông thường thế nào?
static member (variable hoặc function) thuộc về class, không thuộc về instance cụ thể nào — tất cả object chia sẻ cùng 1 bản. Đặc điểm: - Static member variable phải định nghĩa ngoài class (trừ inline static C++17). - Static method không có this…
- Một số STL algorithms quan trọng: `std::sort`, `std::find`, `std::accumulate`, `std::transform` — dùng thế nào?
STL algorithms hoạt động trên bất kỳ container nào qua iterator — tách logic khỏi cấu trúc dữ liệu. Lưu ý: dùng std::sort trên std::list sẽ không compile — list không có random access iterator; phải dùng list.sort().
- `std::set` và `std::multiset` khác nhau thế nào? Khi nào dùng?
std::set std::multiset --------- Duplicate keys Không cho phép Cho phép Cấu trúc Red-Black Tree Red-Black Tree insert O(log n) O(log n) Thứ tự Có (tăng dần mặc định) Có Dùng set khi: cần tập hợp phần tử duy nhất, kiểm tra membership O(log n). Dùng…
- Exception handling trong C++: `try`/`catch`/`throw` hoạt động thế nào? `noexcept` là gì?
Cơ chế: Stack unwinding: khi exception được throw, destructor của mọi object trên stack được gọi theo thứ tự ngược — đây là lý do RAII hoạt động ngay cả khi có exception. noexcept: khai báo hàm không ném exception. Nếu vi phạm → std::terminate()…
- `std::optional<T>` (C++17) là gì? Khi nào dùng thay cho pointer hoặc sentinel value?
std::optional<T đại diện cho giá trị có thể có hoặc không — thay thế cho nullptr, -1, hoặc out-param bool. Dùng khi: hàm có thể thất bại mà không phải lỗi (lookup, parse), optional config field. Không dùng khi: lỗi thực sự — dùng exception;…
- `std::variant<Types...>` (C++17) là gì? Khác `union` thế nào?
std::variant là type-safe union — tại một thời điểm chỉ giữ một giá trị, nhưng luôn biết kiểu đang giữ là gì. Khác union: union std::variant --------- Type tracking Không Có Destructor Không tự gọi Tự gọi An toàn Không (UB nếu đọc sai kiểu)…
- Copy elision, RVO và NRVO trong C++ là gì? Tại sao quan trọng?
- `std::move` vs `std::forward` — khác nhau thế nào? Perfect forwarding là gì?
- `std::string_view` (C++17) là gì? Ưu điểm so với `const std::string&`?
std::stringview là view không sở hữu (non-owning view) vào một chuỗi ký tự — chỉ là con trỏ + độ dài, không copy. So với const std::string&: const std::string& std::stringview --------- const char argument Tạo temporary string Không tạo Substring Tạo string mới Zero-copy Non-null-terminated…
- `std::initializer_list<T>` trong C++11 là gì? Hoạt động thế nào với constructor?
std::initializerlist<T cho phép khởi tạo object bằng cú pháp {...} (brace initialization) với nhiều giá trị — đặc biệt hữu ích cho container. Lưu ý về priority: Hành vi ưu tiên initializerlist constructor khi dùng {} là nguồn gốc nhiều bug ngầm trong C++11.
- `std::thread` và `std::mutex` trong C++11 — cách tạo thread và bảo vệ shared data?
- Sự khác nhau giữa pass-by-value, pass-by-reference, pass-by-pointer trong C++ — khi nào dùng cái nào?
Pass-by-value Pass-by-reference (&) Pass-by-pointer () ------------ Copy Luôn copy Không copy Không copy (copy địa chỉ) Null Không thể null Không thể null Có thể null Reassign Không ảnh hưởng caller Không reassign target Có thể trỏ chỗ khác Dùng Kiểu nhỏ (int, bool) Object…
- Namespace trong C++ là gì? Tại sao không nên `using namespace std;` trong header?
Namespace là vùng tên để nhóm các identifier — tránh xung đột tên khi dùng nhiều library. using namespace std; đưa toàn bộ tên trong std vào scope hiện tại — tiện cho ví dụ nhỏ nhưng nguy hiểm trong code thực. Vấn đề khi…
- Pimpl idiom (Pointer to Implementation) trong C++ là gì? Lợi ích?
- `std::stack`, `std::queue`, `std::priority_queue` — cấu trúc và độ phức tạp?
Ba container adapter trong STL — xây trên một container bên dưới (mặc định deque hoặc vector). Container Thứ tự Mặc định dùng Push Pop Top ------------------ stack LIFO deque O(1) O(1) top() queue FIFO deque O(1) O(1) front() priorityqueue Heap (max ở đầu) vector…
- `struct` và `class` trong C++ khác nhau thế nào?
Khác biệt kỹ thuật duy nhất: mức truy cập mặc định. - struct: thành viên và kế thừa mặc định public. - class: mặc định private. Ngoài ra hai từ khoá hoàn toàn tương đương — struct vẫn có method, constructor, kế thừa, template như…
- `const` và `#define` — nên dùng cái nào, vì sao?
Ưu tiên const (Effective C++, Item 2: "Prefer consts to defines"). define chỉ là thay thế văn bản ở giai đoạn tiền xử lý: - Không có kiểu, không có scope — không tuân theo namespace hay class. - Tên biến mất trước khi compiler…
- Đa hình compile-time và runtime khác nhau thế nào?
Compile-time (static polymorphism): lời gọi được phân giải lúc biên dịch — qua function overloading, template, CRTP. Không tốn chi phí runtime và có thể inline, nhưng kiểu phải biết trước lúc biên dịch. Runtime (dynamic polymorphism): phân giải lúc chạy qua virtual function +…
- Vì sao destructor của lớp cơ sở nên là `virtual`?
Khi xoá object dẫn xuất qua con trỏ lớp cơ sở: Nếu destructor của Base không virtual, chỉ ~Base() chạy — phần Derived không được huỷ → rò rỉ tài nguyên / undefined behavior. Đánh dấu virtual ~Base() để delete tra vtable và gọi đúng…
- Từ khoá `volatile` dùng để làm gì?
volatile báo compiler rằng giá trị biến có thể đổi do tác nhân ngoài luồng chương trình: thanh ghi phần cứng, interrupt/ISR, memory-mapped I/O. Compiler khi đó không được tối ưu kiểu cache biến vào thanh ghi hay bỏ đi lần đọc "thừa" — mỗi…
- Gọi virtual function trong constructor/destructor thì điều gì xảy ra?
- `delete` và `delete[]` khác nhau thế nào?
- delete: huỷ một object đơn (cấp bằng new). Gọi 1 destructor rồi giải phóng vùng nhớ. - delete[]: huỷ một mảng (cấp bằng new[]). Gọi destructor cho từng phần tử rồi giải phóng. Phải khớp cặp: new↔delete, new[]↔delete[]. Trộn lẫn (dùng delete trên mảng,…