C++ Interview Questions: Polymorphism, Vtables, Memory Alignment, STL Containers, and Multithreading Locks
This article presents a comprehensive C++ interview guide covering dynamic polymorphism, vtable mechanics, static vs virtual functions, memory alignment benefits, iterator invalidation in vector and map, erase‑remove idiom, map implementation details, and common synchronization primitives used in multithreaded programming.
The interview was for a position at Dahua, a leader in the security industry, and consisted of three technical rounds followed by an HR round, typically completed within a week.
The department focuses on data mining, distributed storage, machine learning, and virtualization.
Dynamic polymorphism is implemented via virtual function tables (vtable) and a hidden pointer (vptr) in each object; when a base‑class pointer or reference calls a virtual function, the vptr selects the appropriate derived‑class implementation at runtime.
The vtable belongs to the class, not to individual objects; each object contains only the vptr that points to the shared vtable, saving memory.
Static member functions cannot be virtual because they are not associated with any object instance and therefore lack the dynamic dispatch mechanism required for virtual functions.
Destructors are non‑virtual by default to avoid the overhead of storing a vptr in every object; they become virtual only when explicitly declared to ensure proper cleanup through base‑class pointers.
Memory alignment improves access efficiency, reduces fragmentation, and satisfies hardware requirements by aligning data addresses to multiples of their size.
When erasing elements while iterating, iterators may become invalid. For std::vector<int>::iterator , removal shifts elements and invalidates subsequent iterators. For std::map , erasing a node can also invalidate iterators.
A common solution is the erase‑remove idiom for vectors:
vec.erase(std::remove(vec.begin(), vec.end(), value), vec.end());
For maps, use the iterator‑returning erase in a loop:
for (auto it = map.begin(); it != map.end(); ) { if (condition) it = map.erase(it); else ++it; }
Note that C++11 range‑based for loops are not suitable when elements are removed during iteration.
std::map is an ordered associative container typically implemented with a red‑black tree, providing O(log N) operations and guaranteeing element order; std::unordered_map uses a hash table for O(1) average complexity but does not preserve order.
Red‑black trees are chosen over AVL trees because they offer faster insert/delete operations, lower memory overhead, and comparable lookup performance.
At the transport layer, TCP still needs an MSS (Maximum Segment Size) strategy even though IP performs fragmentation, because MSS adapts to varying MTU values along the path to avoid IP‑level fragmentation.
Common C++ multithreading synchronization primitives include mutexes, recursive mutexes, condition variables, read‑write locks, spinlocks, and barriers, each available in the standard library (e.g., std::mutex , std::recursive_mutex , std::condition_variable , std::shared_mutex ).
Deepin Linux
Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.