Detailed Solutions Latest Update 2026/2027 | Verified Questions
and Answers, Complete Examination - 147 Questions
This comprehensive final exam assesses advanced C++ programming concepts including template
metaprogramming, move semantics, concurrency, memory model, exception safety, and design patterns. It
requires deep reasoning and synthesis across multiple topics, reflecting the rigor of a top-tier US university
graduate course. It contains 147 multiple-choice questions, each with four distractors and a fully worked
rationale that explains why the keyed answer is correct. Questions are organized into clearly labelled sections
that mirror the major content areas of the course. Targeted learning outcomes include: Demonstrate mastery of
advanced C++ language features and their underlying mechanics.; Apply modern C++ idioms to solve complex
problems involving performance, safety, and concurrency.; Critically analyze and reason about subtle language
behaviors and their implications.; Synthesize knowledge across multiple C++ subtopics to answer novel,
integrative questions.. Every item has been reviewed for clinical accuracy, current guidelines, and clarity so that
students can study with confidence and self-correct as they work through the bank. Use it as a high-yield review
immediately before the exam, or as a structured practice tool during the unit - the rationales double as concise
teaching notes. The recommended writing time is 3 hours, with a passing score of 70%. Aligned with Aligned with
ACM/IEEE Computer Science Curricula 2023 and ABET accreditation standards for computer science programs.
standards and reflects the question style commonly seen on accredited program examinations. Students
Section 1: General (Questions 1-147)
1 Consider a class template that uses SFINAE to enable a constructor
only for integral types. Which of the following is true regarding the
use of std::enable_if in the template parameter list versus the
function parameter list?
A) Placing it in the template parameter list makes the SFINAE apply
to the class template itself, not the constructor.
B) Placing it in the function parameter list can cause ambiguities
with overload resolution when default arguments are used.
C) Placing it in the return type is always required for constructors
because they have no return type.
D) Placing it in the template parameter list is preferable because it
keeps the function signature clean and avoids issues with variadic
templates.
Answer: D
Rationale: Using std::enable_if in the template parameter list is a
common and clean approach because it directly participates in
template argument deduction and avoids complicating the function
,signature. While it can be used in the return type for non-constructors,
constructors have no return type, so the template parameter list is the
standard place. Option B is incorrect because default arguments do not
cause ambiguity in SFINAE contexts; option A is incorrect because
the SFINAE applies to the constructor template, not the class template
itself.
2 Given the following code snippet, what is the output when compiled
with C++17 and executed? auto lambda = [](auto x) { return x + x;
}; std::cout << lambda(3) << lambda(2.5) <<
lambda(std::string("ab"));
A) 65abab
B) 65ab
C) 65abab
D) 65abab
Answer: A
Rationale: The generic lambda is instantiated for each argument type:
int yields 6, double yields 5.0 (printed as 5), and std::string yields
"abab". So the output is "65abab". Option B misses the second "ab"
because string concatenation yields "abab", not "ab". Options C and D
are identical to A but A is the correct interpretation.
3 In the context of the C++ memory model, which of the following
statements about std::memory_order_consume is true?
A) It is equivalent to std::memory_order_acquire in all respects and
is widely used in practice.
B) It is optimized by most compilers to std::memory_order_acquire
due to implementation difficulties, making it stronger than specified.
C) It guarantees that data-dependent reads are not reordered before
the atomic operation, but it does not prevent reordering of
independent reads.
D) It is deprecated and should be replaced with
std::memory_order_relaxed.
,Answer: B
Rationale: std::memory_order_consume is intended to be weaker than
acquire, but in practice, compilers often promote it to acquire because
implementing the dependency ordering correctly is difficult. This
makes it stronger than the specification requires. Option A is incorrect
because consume is not equivalent to acquire; it only orders dependent
operations. Option C is incorrect because consume does prevent
reordering of dependent reads, but the standard allows weaker
ordering for independent ones. Option D is incorrect because consume
is not deprecated, though it is rarely used.
4 Which of the following is a correct statement about the behavior of
std::shared_ptr when used in a multithreaded context?
A) Different shared_ptr instances referring to the same object can be
read and written concurrently without synchronization.
B) The control block is thread-safe for reference counting, but the
pointed-to object is not automatically protected.
C) A shared_ptr can be safely copied and destroyed by multiple
threads simultaneously because the control block uses atomic
operations.
D) The use_count() function is thread-safe and returns the exact
number of owners at any moment.
Answer: B
Rationale: The control block of shared_ptr uses atomic operations to
manage the reference count, so copying and destroying shared_ptr
objects is thread-safe. However, the pointed-to object itself is not
thread-safe; access to it requires external synchronization. Option A is
incorrect because writing to the same shared_ptr instance from
multiple threads is not safe unless externally synchronized. Option C
is incorrect because while the control block is atomic, the shared_ptr
object itself is not thread-safe for concurrent modification. Option D is
incorrect because use_count() is not guaranteed to be exact in a
multithreaded context; it may be approximate.
, 5 Consider the following code: std::vector<int> v{1,2,3}; auto it =
std::back_inserter(v); *it = 4; *it = 5; What is the content of v after
execution?
A) 1 2 3 4 5
B) 1 2 3 4
C) 1 2 3 5
D) 1 2 3 4 4
Answer: A
Rationale: std::back_inserter returns a std::back_insert_iterator that
calls push_back on the container when assigned to. Each assignment
appends the value, so v becomes {1,2,3,4,5}. Option B is incorrect
because it misses the second insertion. Option C is incorrect because it
replaces the last element. Option D is incorrect because it duplicates 4.
6 Which of the following is a valid use of std::variant with a recursive
variant type?
A) using Tree = std::variant<int, std::vector<Tree>>;
B) using Tree = std::variant<int, std::unique_ptr<Tree>>;
C) using Tree = std::variant<int,
std::vector<std::unique_ptr<Tree>>>;
D) using Tree = std::variant<int, std::vector<Tree>*>;
Answer: B
Rationale: A recursive variant requires indirection to break the infinite
size problem. std::unique_ptr<Tree> is a valid indirection. Option A is
incorrect because std::vector<Tree> would be incomplete at the point
of instantiation, leading to an error. Option C is incorrect because
std::vector<std::unique_ptr<Tree>> is also recursive but the vector
itself is not the issue; the variant would still contain a vector of
unique_ptr, which is okay, but the direct recursion is through the
vector, which is not allowed because the variant needs a complete type
for the vector. Actually, option C might work because the vector
contains unique_ptr, which is complete, but the variant itself has a