All 37 C++ quiz questions below come with a short explanation, visible right on the page — no sign-in needed. They're grouped by beginner and intermediate levels and 37 subtopics, so you can revise one part at a time. Choose Try C++ quiz above to take a scored run and review the questions you got wrong.
How does a reference differ from a pointer in C++?
A.A reference only works with built-in types
B.A reference frees the memory when it goes out of scope
C.A reference binds to an object and cannot be rebound
D.A reference uses less memory than a pointer
Answer: C
A reference must bind to an object at initialization and cannot be rebound. There are no null references, so using it for function parameters eliminates a whole class of null pointer errors.
How do stack objects differ from dynamically allocated ones?
A.Dynamic allocation is always faster than stack allocation
B.A dynamic allocation frees itself when nothing references it
C.The stack can hold far larger objects
D.A stack object is destroyed when it leaves its scope
Answer: D
Stack objects have scope-bound lifetime and are destroyed automatically when they go out of scope. Objects allocated with new live until they are deleted, so forgetting delete leaks and double delete corrupts the heap.
Why does modern C++ advise against calling new/delete by hand?
A.new/delete is slower than a smart pointer
B.Modern compilers no longer support new/delete
C.It leaks easily on an exception or an early return
D.new does not work with user-defined classes
Answer: C
Because it's very easy to leak: an early return or a thrown exception skips the delete line. Smart pointers tie deallocation to the object's lifetime (RAII), so memory is always returned no matter how the function exits.
C.The method is inlined automatically by the compiler
D.The method may not return any value
Answer: B
A const method promises not to modify the object's state, so it can be called on const objects and const references. This is what makes it possible to pass objects by const reference, the most common parameter-passing style in C++.
How does a linker error differ from a compiler error?
A.A link error always names the exact line in the file
B.A link error only happens in optimized builds
C.A link error reports a missing definition for something declared
D.A link error is always a syntax mistake in the source
Answer: C
The compiler only needs a declaration to process a file; the linking step needs the actual definition. That's why missing-symbol errors appear at link time and usually come without a source location, making them harder to track down.
How should a large object be passed to a read-only function?
A.Pass it by raw pointer for flexibility
B.Pass it by const reference
C.Pass it by value for safety
D.Pass it by shared smart pointer
Answer: B
Use a const reference: no copy is made and it promises not to modify. For small types like integers or pointers, passing by value is cheaper because it avoids one level of indirection.
Why is the standard dynamic array container preferred over a raw array?
A.It stores the elements in scattered memory so it is more flexible
B.It accesses elements faster than a raw array
C.It checks the index against the bounds automatically
D.It manages its own memory and knows its own size
Answer: D
It manages its own memory, knows its own size, and grows when needed. A raw array passed to a function loses its size information, and a dynamically allocated array must be freed manually.
How does the standard string class differ from a C-style character pointer?
A.It always allocates dynamic memory for every string
B.It manages its own memory and knows its own length
C.It does not allow accessing individual characters
D.It stores the characters in a multi-byte encoding automatically
Answer: B
It manages its own memory, knows its length, and can append to itself. A C-style string must be scanned to its terminating character to find its length, and concatenation or copying operations must be handled by the calling code to ensure a valid, large enough buffer.
A.The compiler picks the type using the least memory
B.The compiler infers the type from the initializing expression
C.The variable can hold a value of any type at runtime
D.The variable is allocated dynamically rather than on the stack
Answer: B
The compiler deduces the type from the initializer expression at compile time. This is static type inference, not dynamic typing, so there is no runtime cost and the variable's type never changes later.
A.To stop the header being edited from several source files
B.To ensure the include order is fixed
C.To avoid duplicate declarations when a file is included several times
D.To reduce compile time by compressing the content
Answer: C
The preprocessor inserts the entire file content at the include site, so if a header contains definitions or declarations that may not be repeated, including it multiple times causes errors. The include guard mechanism ensures each header is processed only once per translation unit.
What problem does RAII (tying resources to object lifetime) solve in C++?
A.Memory is collected automatically as in a garbage-collected language
B.The resource is released even when an exception occurs
C.The program runs faster from fewer allocations
D.The object can be shared safely between threads
Answer: B
It guarantees resources are released even when a function throws an exception, because the destructor always runs during stack unwinding. This is the foundation of smart pointers, std::lock_guard, and wrapper classes for files or connections.
How does a unique-ownership smart pointer differ from a shared one?
A.The unique one cannot be copied and needs no counter
B.The unique one does not free the object when it leaves scope
C.The shared one does not work with user-defined classes
D.The unique one only works for arrays
Answer: A
An exclusive-ownership pointer cannot be copied, only transfers ownership, and carries no counter overhead. A shared pointer maintains a thread-safe reference count, so it costs more and should be used only when ownership is genuinely shared.
A.The object becomes safe to use from several threads
B.The compiler skips the constructor and destructor
C.The source object is freed immediately
D.The resource is transferred rather than duplicated
Answer: D
Moving takes the source object's resources instead of duplicating data. Returning a large container from a function or inserting it into another container is therefore no longer as expensive as before.
Why does a class with a custom destructor usually need copy and move operations too?
A.The default copy causes a double free
B.The language standard requires those functions
C.The compiler refuses to compile a class missing them
D.Without them the class cannot be used in a container
Answer: A
A user-written destructor usually means the class manages a raw resource. The default copy only copies the pointer, so two objects point to the same resource and both free it when destroyed.
What happens when deleting a derived object through a base pointer without a virtual destructor?
A.Undefined behaviour, and the derived part is not destroyed
B.The object is destroyed fully but more slowly
C.The program stops immediately with a clear message
D.The compiler reports an error at compile time
Answer: A
This is undefined behavior, and the common symptom is that the derived class's destructor does not run, leaking the resources it manages. A base class used for polymorphism must have a virtual destructor.
What happens when assigning a derived object to a base-typed variable by value?
A.The derived class's own data is sliced away
B.The object keeps the derived class's polymorphic behaviour
C.The program stops immediately when it reaches that line
D.The compiler rejects the assignment
Answer: A
The derived class's own data and behavior are sliced off: the variable only has room for the base-class part. The code compiles and produces no runtime error, making this a silent, hard-to-detect bug.
D.At runtime, with the type passed in as a parameter
Answer: B
Templates are processed at compile time: the compiler generates a separate instantiation for each type used. There is no runtime cost, but compile time and code size grow with the number of distinct types.
Frequent key lookups with no ordering requirement. Which container fits?
A.A linked list for fast insertion and removal
B.A dynamic array scanned sequentially on each lookup
C.A hash table with average constant-time lookup
D.A balanced search tree for a guaranteed lookup time
Answer: C
Use a hash table: average constant-time lookup with no ordering cost. A balanced search tree is only worth it when you need ordered key traversal or a tight worst-case guarantee.
What happens when inserting into a dynamic array while iterating it?
A.The new element is always appended after the loop
B.The program errors right at the line that adds the element
C.The loop automatically skips the newly added element
D.The iterators can become invalid
Answer: D
The iterator may become invalidated: when the container reallocates, all elements move to new memory and the old iterator points to freed memory. Continuing to use it is undefined behavior, often not failing immediately and thus very hard to track down.
What does the strong exception safety guarantee mean?
A.On failure the state is left exactly as it was
B.Memory is freed automatically when an exception occurs
C.The operation is guaranteed never to throw
D.The exception is always caught inside the function
Answer: A
The strong guarantee means if the operation throws, the state stays exactly as it was before the call, with no partial changes. It's the middle of three levels: basic, strong, and nothrow.
What problem does the standard optional type solve?
A.Allocating the contained value dynamically
B.Expressing absence without needing a pointer
C.Guaranteeing the value is initialized before use
D.Letting a variable hold several different types
Answer: B
It expresses a value that may be absent without needing a pointer or a sentinel value like minus one. The return type makes it explicit that there may be no result, so the caller is forced to check instead of forgetting.
What is the risk of capturing by reference in a lambda?
A.The lambda must allocate dynamically to hold the reference
B.The lambda cannot modify a variable captured by reference
C.The lambda can outlive the captured variable
D.The lambda cannot be passed to another function
Answer: C
The risk is that the lambda outlives the captured variable: once the original variable goes out of scope, the reference dangles and calling the lambda later is undefined behavior. This is a very common bug with lambdas that run asynchronously.
What does marking a function as compile-time evaluable give you?
A.The function may take no input parameters
B.The function is always evaluated at compile time
C.The function is evaluated at compile time when the input is constant
D.The compiler is forced to inline the function
Answer: C
The function can be evaluated at compile time if all inputs are constants, and the result becomes a constant inlined directly into the code. If the inputs are only known at runtime, it still runs normally as an ordinary function.
Why is undefined behaviour in C++ more dangerous than an ordinary bug?
A.It only occurs in optimized builds
B.It always stops the program immediately
C.The compiler is entitled to assume it never happens
D.Static analysis tools always detect it
Answer: C
Because the compiler is allowed to assume it never happens. On that assumption, the optimizer can delete even the checks the programmer wrote, so the program behaves completely differently from the intent with no warning at all.
Why is iterating a dynamic array usually faster than a linked list at the same complexity?
A.The compiler cannot optimize a linked list
B.A dynamic array uses fewer machine instructions per element
C.The data is contiguous so it uses the cache well
D.A linked list must be reordered while iterating
Answer: C
Because the elements are contiguous in memory, so when the processor loads one block, the following elements are already in cache. A linked list follows pointers to scattered regions, and each step can be a memory stall.
What happens if a thread object is destroyed without join or detach?
A.The thread is cancelled safely midway
B.The compiler reports an error at compile time
C.The thread carries on until its work is done
D.The program is terminated immediately
Answer: D
The program is terminated immediately. The standard library chooses to abort rather than guess whether the programmer wanted to wait or to let the thread run free, since both implicit choices are dangerous.
Why use std::lock_guard instead of calling lock() and unlock() by hand?
A.The mutex is released even when the function throws
B.The lock class lets several threads enter at once
C.The lock class is faster under heavy contention
D.The lock class detects and prevents deadlock automatically
Answer: A
The mutex is released automatically when leaving scope, even if the function throws or returns early. Forgetting unlock() on such a branch is a classic cause of deadlock.
Two threads writing an ordinary integer without synchronisation is what?
A.Only wrong when the value exceeds one machine word
B.Safe if the two threads run on different cores
C.A data race, which is undefined behaviour
D.Safe, because an integer assignment is atomic
Answer: C
That's a data race, and the standard treats it as undefined behavior. What makes it dangerous is that the program usually runs fine during testing and only misbehaves under load, so the bug slips into production very easily.
Why must a condition be rechecked after a condition variable wakes a thread?
A.The condition variable does not hold the lock on waking
B.The thread can wake while the condition is still unmet
C.Rechecking speeds up the wakeup process
D.The standard requires every wait call to sit in a loop
Answer: B
Because the thread can wake up while the condition isn't satisfied: both from spurious wakeups and because another thread already took the data first. So the wait call must sit inside a loop that checks the condition, or take the predicate as an argument.
Why prefer standard library algorithms over hand-written loops?
A.A standard algorithm runs across several cores automatically
B.A hand-written loop cannot be used with standard containers
C.The intent is clearer and classic boundary bugs are avoided
D.A standard algorithm is always faster than a hand-written loop
Answer: C
The intent of the code shows up right in the algorithm's name, and boundary errors like off-by-one are eliminated. Speed is usually equivalent because both are inlined, so the main benefit lies in readability and correctness.
What is the cost of storing a lambda in the standard general-purpose function type?
A.The lambda loses the ability to capture from the enclosing scope
B.It may require dynamic allocation and an indirect call
C.The lambda can only be called once
D.The lambda no longer takes parameters
Answer: B
This type erases type information, so the call becomes an indirect call and may require dynamic allocation for the captured state. Passing a lambda through a template parameter lets the compiler inline it and costs nothing.
How does a scoped enumeration differ from an unscoped one?
A.It only accepts positive integer values
B.You cannot assign a specific value to each member
C.It cannot be used in a value-based branch statement
D.It does not convert to an integer implicitly and the names are scoped
Answer: D
A scoped type does not implicitly convert to an integer, and member names live in their own scope. This prevents accidentally comparing two different enum types and avoids name clashes with other things in the same scope.
What does putting a helper function in an unnamed namespace achieve?
A.The compiler is forced to inline the function
B.The function is loaded before the program starts running
C.The function is only visible within that source file
D.The function cannot be called from that file
Answer: C
The function has internal linkage: it is visible only in that source file, so two files defining a function with the same name do not conflict at link time. This is also a way to narrow a module's public surface.
What does declaring a dependency as private mean in the build system?
A.That library is only used in debug builds
B.That library is linked statically rather than dynamically
C.That library is loaded at runtime rather than at build time
D.The dependency does not propagate to other targets
Answer: D
The dependency does not propagate to other targets that use this library. It is correct when that library appears only in the implementation; if its types appear in a public header, it must be declared as propagated.
How does static linking differ from dynamic linking in deployment?
A.Dynamic cannot be used with third-party libraries
B.Static allows updating a library without rebuilding
C.Static embeds the code while dynamic loads it at runtime
D.Static always runs faster than dynamic
Answer: C
Static linking embeds the library code into the program, so the file is larger but runs without the library being present on the target machine. Dynamic linking loads at runtime, so updating the library does not require rebuilding the program.
What does structured binding of multiple return values buy you?
A.Guaranteeing the values are never null
B.Avoiding copies entirely when extracting the values
C.Naming each component clearly rather than using indices
D.Letting a function return several values with no return type
Answer: C
It lets you give each component a clear name instead of accessing by position, making the code much easier to read. It is especially handy when iterating a map container, where each element consists of a key and a value.
What matters most when handling Vietnamese text in C++?
A.A string stores bytes and one character can span several
B.String comparison always follows alphabetical order
C.Strings normalize their diacritics into one form automatically
D.A wide character type must be used for all text
Answer: A
Strings in C++ store bytes, not characters, so a single accented Vietnamese letter occupies multiple bytes. The returned length is a byte count, and slicing by byte index can cut in the middle of a character, producing corrupted data.