CT 301 Exam 1 Practice Problems
A 28-problem practice set covering the same concepts as Exam 1. The HW#1-style problems use a Library domain (not the Inventory domain from HW#1) so that working through them does not give away your HW#1 answers; they test the same underlying patterns (polymorphic dispatch, unique_ptr ownership, state machines) on a different system.
Try the problems first. Answers and explanations are in a separate file.
Section A: Types, initialization, auto (3 problems)
Problem 1 [easy]
What is the type of n after the following line?
auto n = 100ul;
A. int B. long C. unsigned long D. unsigned int
Problem 2 [medium]
Which of the following lines compile?
A. int a = 7; B. int b {7}; C. int c = 7.0; D. int d {7.0}; E. auto e = 7.0;
Problem 3 [medium]
What does this code print?
auto x = 3;
auto y = 3.0;
auto z = x / 2;
auto w = y / 2;
std::cout << z << " " << w << "\n";
A. 1 1 B. 1 1.5 C. 1.5 1.5 D. 1 1.50000
Section B: Const, references, pointers (6 problems)
Problem 4 [easy]
Which of the following is a pointer to a constant integer (the integer cannot be modified through the pointer, but the pointer itself can be reseated)?
A. int* const p; B. const int* p; C. const int* const p; D. int& p;
Problem 5 [medium]
Given int x = 5;, which of the following lines fail to compile?
A. const int* p = &x; B. int& r = x; C. int& r = 7; D. const int& cr = 7; E. int* const q = &x; q = nullptr;
Problem 6 [medium]
What does this code print?
int a = 10;
int b = 20;
const int* p = &a;
p = &b;
std::cout << *p << "\n";
A. 10 B. 20 C. The code does not compile because p is a pointer-to-const. D. The code does not compile because &b cannot bind to const int*.
Problem 7 [hard]
Consider:
void swap_values(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
int main() {
int x = 1, y = 2;
swap_values(x, y);
std::cout << x << " " << y << "\n";
}
What does the program print?
A. 1 2 B. 2 1 C. The code does not compile because int& cannot bind to a local variable. D. The code compiles but prints 1 2 because references are copies of the value.
Problem 8 [hard]
Consider:
int& get_first(int* arr) {
return arr[0];
}
int main() {
int v[3] = {10, 20, 30};
get_first(v) = 99;
std::cout << v[0] << "\n";
}
What does the program print?
A. 10 B. 99 C. The code does not compile because you cannot assign to a function call. D. The code compiles but v[0] is unchanged because the reference is to a copy.
Problem 9 [very hard]
Consider:
constexpr int square(int x) { return x * x; }
int read_number(); // defined elsewhere, returns int at runtime
constexpr int a = square(5); // line 1
constexpr int b = square(read_number()); // line 2
const int c = read_number(); // line 3
const int d = square(7); // line 4
constexpr int e = square(read_number()); // line 5 (duplicate of 2 for clarity)
Which of these lines compile?
A. Only line 1 B. Lines 1, 3, 4 C. Lines 1, 2, 3, 4 D. All five lines
Section C: Enums, structs, classes, headers (4 problems)
Problem 10 [easy]
Consider:
struct Point {
int x;
int y;
};
class Vector {
int dx;
int dy;
};
int main() {
Point p {1, 2};
p.x = 5; // line A
Vector v {3, 4};
v.dx = 5; // line B
}
Which lines compile?
A. Only line A B. Only line B C. Both D. Neither
Problem 11 [medium]
Consider:
enum class Mode { Read, Write, Append };
enum Direction { Up, Down };
Mode m1 = Mode::Read; // line 1
Mode m2 = Read; // line 2
Direction d1 = Up; // line 3
int n = m1; // line 4
int k = d1; // line 5
bool b = (m1 == Mode::Write); // line 6
bool c = (d1 == Up); // line 7
Which lines compile?
A. 1, 3, 5, 6, 7 B. 1, 3, 4, 5, 6, 7 C. All seven lines D. Only 1, 3, 6
Problem 12 [medium]
You are writing a header geometry.h that will be included by multiple .cpp files. Which of the following can you safely place in geometry.h without causing link errors?
A. class Point; (forward declaration) B. double distance(Point a, Point b); (function declaration, no body) C. double distance(Point a, Point b) { / ... / } (non-inline function definition) D. inline double TWO_PI = 6.2832; E. int g_count = 0; (a plain global variable definition)
Problem 13 [hard]
Consider this header, included by both main.cpp and helper.cpp:
// shapes.h
#pragma once
enum class Style { Solid, Dashed };
inline Style default_style() { return Style::Solid; }
int shape_count = 0; // line X
The program is linked from both translation units. What happens?
A. Compiles and links cleanly. B. Link error: shape_count is defined in both translation units. C. Compile error: enum class cannot appear in a header. D. Link error: default_style is defined in both translation units.
Section D: Functions in depth (5 problems)
Problem 14 [easy]
Which parameter mode best fits a function whose job is to compute the average of a large std::vector without modifying it?
A. double avg(std::vector B. double avg(std::vector C. double avg(const std::vector D. double avg(std::vector
Problem 15 [medium]
Given the declarations:
void process(int x);
void process(double x);
void process(int x, int y);
Which additional declaration would cause an overload conflict (the compiler will reject)?
A. int process(int x); B. void process(unsigned x); C. void process(const std::string& s); D. void process(int x, double y);
Problem 16 [hard]
Consider:
void shift(std::vector<int>& v, int amount) {
for (int& x : v) x += amount;
}
int main() {
std::vector<int> data {1, 2, 3};
shift(data, 10);
for (int x : data) std::cout << x << " ";
std::cout << "\n";
}
What does the program print?
A. 1 2 3 B. 10 20 30 C. 11 12 13 D. The code does not compile because int& cannot bind to a std::vector element.
Problem 17 [hard]
Consider:
std::string greet(const std::string& name) {
return "hello " + name;
}
std::string greet(std::string name) {
return "HELLO " + name;
}
int main() {
std::string n = "world";
std::cout << greet(n) << "\n";
}
What happens?
A. Prints hello world. B. Prints HELLO world. C. The code compiles but the call is ambiguous; the compiler rejects main. D. The code does not compile because two overloads of greet cannot return the same type.
Problem 18 [very hard]
Consider:
void add_exclaim(std::string s) {
s += "!";
}
void make_loud(std::string& s) {
for (char& c : s) c = std::toupper(c);
}
int main() {
std::string msg = "hello";
add_exclaim(msg);
make_loud(msg);
std::cout << msg << "\n";
}
What does the program print?
A. hello B. hello! C. HELLO D. HELLO!
Section E: Classes, virtual functions, inheritance (5 problems)
Problem 19 [easy]
Consider:
class Animal {
public:
virtual void speak() const = 0;
};
int main() {
Animal a;
a.speak();
}
What happens?
A. The program prints nothing. B. The code compiles but crashes at runtime. C. The code does not compile because Animal is abstract and cannot be instantiated. D. The code compiles and prints a default message.
Problem 20 [medium]
Which of the following are valid signatures for overriding a base class function declared as virtual int rank() const;?
A. int rank() const override; B. virtual int rank() const override; C. int rank() override; D. int rank() const; (no override keyword)
Problem 21 [hard]
Consider:
class Base {
public:
virtual ~Base() = default;
virtual std::string greet() const { return "base"; }
};
class Derived : public Base {
public:
std::string greet() const override { return "derived"; }
};
void show(const Base& b) {
std::cout << b.greet() << "\n";
}
int main() {
Derived d;
Base b;
show(d);
show(b);
}
What does the program print?
A. base then base B. derived then base C. derived then derived D. The code does not compile because Base cannot be instantiated.
Problem 22 [hard]
Consider:
class Widget {
const int id_;
int& counter_;
public:
Widget(int id, int& c) /* CHOOSE INITIALIZER */ {}
};
Which of the following are valid replacements for the CHOOSE INITIALIZER placeholder so that Widget compiles?
A. : id_{id}, counter_{c} B. : counter_{c}, id_{id} C. (no initializer list; assign id_ = id; and counter_ = c; in the body) D. : id_(id), counter_(c) E. : id_{id} (and leave counter_ defaulted)
Problem 23 [very hard]
Consider:
class Shape {
public:
virtual double area() const { return 0.0; }
virtual ~Shape() = default;
};
class Circle : public Shape {
double r_;
public:
Circle(double r) : r_(r) {}
double area() { return 3.14 * r_ * r_; } // line X
};
void print_area(const Shape& s) {
std::cout << s.area() << "\n";
}
int main() {
Circle c(2.0);
print_area(c);
}
What does the program print?
A. 12.56 B. 0 C. The code does not compile. D. The output is undefined.
Section F: Container ownership and state machines (5 problems, Library domain)
The following problems use a simplified library system, NOT the HW#1 inventory system. Refer to this overview when answering:
Abstract class LibraryItem with derived Book, Periodical, Reference.
Each LibraryItem has:
virtual bool canCirculate() const = 0;
virtual bool canBeLost() const = 0;
virtual std::string attribute(const std::string& key) const;
Rules:
Book::canCirculate() = true;
Periodical::canCirculate() = false;
Reference::canCirculate() = false;
Book::canBeLost() = true;
Periodical::canBeLost() = true;
Reference::canBeLost() = false;
States: Available, CheckedOut, Lost
A Collection owns items as std::vector<std::unique_ptr<LibraryItem>>
across three state vectors:
available_, checkedOut_, lost_
Verbs:
CHECKOUT Available -> CheckedOut (must canCirculate())
RETURN CheckedOut -> Available
REPORT_LOST Available or CheckedOut -> Lost (must canBeLost())
CATALOG ADD a new item to Available
Problem 24 [medium]
When the call auto results = coll.select_by("category", "fiction"); returns, which is true about the items pointed to by elements of results?
A. Ownership has transferred to the caller; the caller must delete each pointer. B. The items are still owned by the Collection; results provides non-owning views. C. The items have been removed from their state vectors and placed in a holding buffer. D. Each element of results is a deep copy of a LibraryItem.
Problem 25 [hard]
Which of the following actions are valid (will succeed) in the Library system, assuming the items exist in the expected states?
A. CHECKOUT a Book that is currently Available. B. CHECKOUT a Periodical that is currently Available. C. RETURN a Reference that is currently Available. D. REPORT_LOST a Reference that is currently Available. E. CATALOG a newly-constructed Book to the Available state. F. RETURN a Book that is currently CheckedOut.
Problem 26 [hard]
Inside Collection::checkout, an item is moved from available_ to checkedOut_ with this code:
checkedOut_.push_back(std::move(*it)); // line A
available_.erase(it); // line B
A student proposes swapping the order (erase first, then push_back). Which is the BEST description of what happens?
A. The two orderings are equivalent because unique_ptr move is atomic. B. The swapped version is undefined behavior: erase invalidates it and destroys the unique_ptr (which deletes the LibraryItem), so the subsequent *it dereferences an invalid iterator. C. The swapped version does not compile because you cannot use it after erase. D. The swapped version compiles but leaks memory because the LibraryItem is constructed twice.
Problem 27 [very hard]
A Collection contains, in available_: 4 Books (all circulating, all loseable), 2 Periodicals, 3 References. A patron calls checkout on the entire available_ view. How many items end up in checkedOut_, and how many appear in the rejects list?
A. 9 in checkedOut_, 0 rejects. B. 4 in checkedOut_, 5 rejects (the Periodicals and References, since neither can circulate). C. 6 in checkedOut_, 3 rejects (the References). D. 0 in checkedOut_, 9 rejects (mixed selections are not supported).
Problem 28 [difficult]
Consider this excerpt of the Library implementation:
std::string Book::attribute(const std::string& key) const {
if (key == "id") return id_;
if (key == "title") return title_;
if (key == "category") return category();
if (key == "fiction") return fiction_ ? "true" : "false";
if (key == "author") return author_;
return LibraryItem::attribute(key);
}
std::vector<LibraryItem*> Collection::select_by(const std::string& key,
const std::string& value) const {
std::vector<LibraryItem*> result;
for (const auto& p : available_) {
if (p->attribute(key) == value) result.push_back(p.get());
}
return result;
}
Suppose a patron runs select_by("fiction", "true"). The available_ vector contains:
- 5 Books: 3 with
fiction_ == true, 2 withfiction_ == false. - 2 Periodicals.
- 3 References.
Assume Periodical::attribute("fiction") returns "false" and Reference::attribute("fiction") returns "false". How many items does the selection return, and why?
A. 5 items (all Books match because fiction is a Book-only attribute). B. 3 items (only the Books whose fiction_ is true). C. 0 items (the base class throws on Periodical and Reference). D. 10 items (all Books plus all Periodicals).