Practice Questions — Modern C++ Features (C++11 to C++20)
← Back to NotesTopic-Specific Questions
Question 1
Easy
What is the output?
auto x = 42;
auto y = 3.14;
cout << sizeof(x) << " " << sizeof(y);auto deduces int for 42 and double for 3.14.
4 8Question 2
Easy
What is the output?
vector<int> v = {10, 20, 30};
for (auto x : v) x *= 2;
for (auto x : v) cout << x << " ";auto x (not auto& x) creates a copy.
10 20 30Question 3
Easy
What is the output?
vector<int> v = {10, 20, 30};
for (auto& x : v) x *= 2;
for (auto x : v) cout << x << " ";auto& x is a reference -- modifying x modifies the vector.
20 40 60Question 4
Easy
What is the output?
auto sq = [](int x) { return x * x; };
cout << sq(5) << " " << sq(3);Lambda that squares its argument.
25 9Question 5
Easy
What is the output?
int a = 10;
auto add = [a](int x) { return x + a; };
a = 20;
cout << add(5);Capture by value copies the value at the time of lambda creation.
15Question 6
Medium
What is the output?
int a = 10;
auto add = [&a](int x) { return x + a; };
a = 20;
cout << add(5);Capture by reference: the lambda sees the current value of a.
25Question 7
Medium
What is the output?
pair<string, int> p = {"Arjun", 85};
auto [name, marks] = p;
marks = 90;
cout << p.second << " " << marks;Structured bindings create copies by default (auto, not auto&).
85 90Question 8
Medium
What is the output?
pair<string, int> p = {"Arjun", 85};
auto& [name, marks] = p;
marks = 90;
cout << p.second;auto& structured bindings are references.
90Question 9
Medium
What is the output?
constexpr int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
cout << fib(7);constexpr recursive Fibonacci.
13Question 10
Medium
What is the output?
auto print = [](auto x) { cout << x << " "; };
print(42);
print(3.14);
print("hello");Generic lambda (C++14): auto parameter works like a template.
42 3.14 helloQuestion 11
Hard
What is the output?
auto counter = [n = 0]() mutable { return ++n; };
cout << counter() << " " << counter() << " " << counter();Init capture (n = 0) creates a variable inside the lambda. mutable allows modification.
1 2 3Question 12
Hard
What is the output?
optional<int> val;
cout << val.has_value() << " ";
val = 42;
cout << val.has_value() << " " << val.value() << " ";
val.reset();
cout << val.value_or(-1);optional can hold a value or be empty. value_or returns the default if empty.
0 1 42 -1Question 13
Hard
What is the output?
enum class Direction { Up = 1, Down = 2, Left = 3, Right = 4 };
Direction d = Direction::Left;
cout << static_cast<int>(d);
// cout << d; // Would NOT compile: no implicit conversionenum class requires explicit cast to int.
3Question 14
Easy
What is the output?
auto p = make_pair(10, 20);
cout << p.first << " " << p.second;make_pair creates a pair. auto deduces pair.
10 20Question 15
Medium
What is the output?
vector<int> v = {1, 2, 3, 4, 5};
auto sum = [](const vector<int>& vec) {
int s = 0;
for (auto x : vec) s += x;
return s;
};
cout << sum(v);Lambda that computes the sum of a vector.
15Question 16
Medium
What is the output?
constexpr int square(int x) { return x * x; }
constexpr int a = square(3);
constexpr int b = square(4);
cout << a + b;constexpr evaluates at compile time.
25Question 17
Hard
What is the output?
auto apply = [](auto f, auto x) { return f(x); };
auto twice = [](int x) { return x * 2; };
auto negate = [](int x) { return -x; };
cout << apply(twice, 5) << " " << apply(negate, 3);Higher-order generic lambda: takes a function and an argument.
10 -3Question 18
Easy
What is the output?
using IntVec = vector<int>;
IntVec v = {5, 10, 15};
cout << v.size() << " " << v[2];using creates a type alias. IntVec is vector.
3 15Mixed & Application Questions
Question 1
Easy
What is the output?
int* p = nullptr;
cout << (p == nullptr);nullptr is the type-safe null pointer constant.
1Question 2
Easy
What is the output?
vector<int> v{1, 2, 3, 4, 5};
cout << v.size();Uniform initialization with braces creates a vector with 5 elements.
5Question 3
Easy
What is the output?
auto add = [](int a, int b) { return a + b; };
cout << add(10, 20);Lambda that adds two integers.
30Question 4
Medium
What is the output?
vector<int> v = {5, 3, 1, 4, 2};
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
cout << v[0] << " " << v[4];Lambda comparator returns true if a should come before b.
5 1Question 5
Medium
What is the output?
auto [a, b, c] = tuple{10, 20, 30};
cout << a + b + c;Structured bindings unpack a tuple.
60Question 6
Medium
What is the output?
map<string, int> m = {{"a", 1}, {"b", 2}};
if (auto it = m.find("b"); it != m.end())
cout << it->second;
else
cout << "not found";C++17 if-with-initializer: the variable is scoped to the if/else.
2Question 7
Medium
What is the output?
constexpr int N = 5;
int arr[N] = {1, 2, 3, 4, 5};
cout << arr[N - 1];constexpr values can be used as array sizes.
5Question 8
Hard
What is the output?
vector<int> v = {1, 2, 3, 4, 5};
auto even = [](int x) { return x % 2 == 0; };
int cnt = count_if(v.begin(), v.end(), even);
auto it = find_if(v.begin(), v.end(), even);
cout << cnt << " " << *it;count_if counts matching elements. find_if finds the first match.
2 2Question 9
Hard
What is the output?
auto make_adder = [](int n) {
return [n](int x) { return x + n; };
};
auto add5 = make_adder(5);
auto add10 = make_adder(10);
cout << add5(3) << " " << add10(3);A lambda that returns a lambda (closure factory).
8 13Question 10
Hard
What is the output?
auto fib = [](auto self, int n) -> int {
if (n <= 1) return n;
return self(self, n - 1) + self(self, n - 2);
};
cout << fib(fib, 8);A recursive lambda using the self-passing trick.
21Question 11
Medium
What is the difference between capture by value [x] and capture by reference [&x] in lambdas?
Think about when the value is read and whether modifications are visible.
Capture by value [x] copies the variable at lambda creation time. The lambda has its own copy; changes to the original do not affect the lambda, and the lambda cannot modify the original (unless
mutable is used, which modifies the copy). Capture by reference [&x] stores a reference to the original variable. The lambda always sees the current value, and modifications through the lambda affect the original.Question 12
Hard
What problems does C++20 concepts solve that SFINAE and enable_if had?
Think about error messages and readability.
SFINAE (Substitution Failure Is Not An Error) and
enable_if produce extremely cryptic error messages when template constraints are violated -- often dozens of lines of nested template instantiation errors. Concepts provide clear, readable error messages like "T does not satisfy Numeric." They also make the intent readable in the code itself: template<Numeric T> is immediately clear, while template<typename T, typename = enable_if_t<is_arithmetic_v<T>>> is nearly unreadable.Multiple Choice Questions
MCQ 1
What does the auto keyword do in C++11?
Answer: B
B is correct. In C++11,
B is correct. In C++11,
auto was repurposed for type deduction. The compiler infers the type from the initializer expression.MCQ 2
What is nullptr in C++11?
Answer: B
B is correct.
B is correct.
nullptr has type std::nullptr_t and unambiguously represents a null pointer, unlike NULL which is an integer 0.MCQ 3
Which C++ standard introduced lambdas?
Answer: B
B is correct. Lambda expressions were introduced in C++11. C++14 added generic lambdas (auto parameters).
B is correct. Lambda expressions were introduced in C++11. C++14 added generic lambdas (auto parameters).
MCQ 4
What does constexpr mean?
Answer: B
B is correct.
B is correct.
constexpr indicates that a function or variable can be evaluated at compile time when given constant arguments. It can also be called at runtime.MCQ 5
What is the syntax for a range-based for loop?
Answer: B
B is correct. The C++11 range-based for loop uses the colon syntax:
B is correct. The C++11 range-based for loop uses the colon syntax:
for (auto x : container).MCQ 6
What is the difference between enum and enum class?
Answer: B
B is correct.
B is correct.
enum class (scoped enumeration) requires the scope operator (Color::Red) and does not implicitly convert to int. Regular enum pollutes the enclosing scope and allows implicit int conversion.MCQ 7
What does [&] in a lambda capture clause mean?
Answer: B
B is correct.
B is correct.
[&] captures all variables used in the lambda by reference. [=] captures all by value. [this] captures the this pointer.MCQ 8
Which C++ standard introduced structured bindings (auto [x, y] = pair)?
Answer: C
C is correct. Structured bindings were introduced in C++17. They work with pairs, tuples, arrays, and structs with public members.
C is correct. Structured bindings were introduced in C++17. They work with pairs, tuples, arrays, and structs with public members.
MCQ 9
What does std::optional represent?
Answer: B
B is correct.
B is correct.
std::optional<T> either contains a value of type T or is empty (nullopt). It replaces sentinel values like -1 or nullptr for indicating missing data.MCQ 10
What is string_view in C++17?
Answer: B
B is correct.
B is correct.
string_view provides a lightweight, non-owning view into character data. It avoids copying strings when you only need to read them.MCQ 11
What does the spaceship operator (<=>) do in C++20?
Answer: B
B is correct. The three-way comparison operator
B is correct. The three-way comparison operator
<=> returns a comparison category (strong_ordering, weak_ordering, partial_ordering). With = default, the compiler generates all six comparison operators automatically.MCQ 12
What are C++20 concepts?
Answer: B
B is correct. Concepts are named compile-time predicates that constrain template parameters. They replace SFINAE with readable syntax and produce clear error messages when constraints are not met.
B is correct. Concepts are named compile-time predicates that constrain template parameters. They replace SFINAE with readable syntax and produce clear error messages when constraints are not met.
MCQ 13
What does auto [x, y] = make_pair(1, 2); do?
Answer: A
A is correct. Structured bindings decompose the pair: x gets first (1), y gets second (2). This eliminates the need for .first and .second.
A is correct. Structured bindings decompose the pair: x gets first (1), y gets second (2). This eliminates the need for .first and .second.
MCQ 14
What is the advantage of using over typedef?
Answer: B
B is correct.
B is correct.
using supports template aliases: template<typename T> using Vec = vector<T>;. This is impossible with typedef. The syntax is also more readable: using F = int(*)(double); vs typedef int(*F)(double);.MCQ 15
What does the mutable keyword do in a lambda?
Answer: B
B is correct. By default, variables captured by value are const inside the lambda.
B is correct. By default, variables captured by value are const inside the lambda.
mutable removes this restriction, allowing the lambda to modify its captured copies (not the originals).MCQ 16
What is the correct way to declare a lambda that takes no parameters and returns void?
Answer: B
B is correct. The syntax is
B is correct. The syntax is
[]() {}: empty capture, no parameters, empty body. The parentheses can be omitted if there are no parameters: [] {} is also valid.MCQ 17
Which C++ standard introduced generic lambdas (auto parameters)?
Answer: B
B is correct. C++14 introduced generic lambdas where parameters can be declared with
B is correct. C++14 introduced generic lambdas where parameters can be declared with
auto, making the lambda act like a template function.MCQ 18
What does value_or(default) do on a std::optional?
Answer: B
B is correct.
B is correct.
value_or(default) returns the contained value if the optional has one, or the specified default if it is empty (nullopt).Coding Challenges
Challenge 1: Sort Structs Using Lambda Comparator
EasyCreate a vector of Student structs (name, marks, grade). Sort by marks descending using a lambda. Print the sorted list using range-based for with structured bindings.
Sample Input
{"Arjun", 85, 'B'}, {"Priya", 92, 'A'}, {"Kiran", 78, 'B'}, {"Neha", 92, 'A'}
Sample Output
Neha: 92 (A)
Priya: 92 (A)
Arjun: 85 (B)
Kiran: 78 (B)
Use auto, lambda, range-based for, and structured bindings. No old-style loops.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Student {
string name;
int marks;
char grade;
};
int main() {
vector<Student> students = {
{"Arjun", 85, 'B'}, {"Priya", 92, 'A'},
{"Kiran", 78, 'B'}, {"Neha", 92, 'A'}
};
sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
if (a.marks != b.marks) return a.marks > b.marks;
return a.name < b.name;
});
for (const auto& [name, marks, grade] : students)
cout << name << ": " << marks << " (" << grade << ")" << endl;
return 0;
}Challenge 2: Build a Closure Factory for Math Operations
MediumCreate a function that returns a lambda. Given an operation string ("add", "multiply", "power"), return a lambda that performs that operation with a fixed operand. Demonstrate calling the returned lambdas.
Sample Input
makeOp("add", 5), makeOp("multiply", 3), makeOp("power", 2)
Sample Output
add5(10) = 15
mul3(10) = 30
pow2(10) = 100
Use C++14 generic lambdas and closures. No if/else chains inside the lambdas themselves.
#include <iostream>
#include <functional>
#include <cmath>
using namespace std;
function<int(int)> makeOp(const string& op, int n) {
if (op == "add")
return [n](int x) { return x + n; };
if (op == "multiply")
return [n](int x) { return x * n; };
if (op == "power")
return [n](int x) { return (int)pow(x, n); };
return [](int x) { return x; };
}
int main() {
auto add5 = makeOp("add", 5);
auto mul3 = makeOp("multiply", 3);
auto pow2 = makeOp("power", 2);
cout << "add5(10) = " << add5(10) << endl;
cout << "mul3(10) = " << mul3(10) << endl;
cout << "pow2(10) = " << pow2(10) << endl;
return 0;
}Challenge 3: Compile-Time Lookup Table with constexpr
MediumCreate a constexpr function that computes factorial. Use it to build a compile-time array of factorials from 0! to 12!. Print the table at runtime.
Sample Input
Factorials 0 to 12
Sample Output
0! = 1
1! = 1
2! = 2
...
12! = 479001600
The factorial table must be computed entirely at compile time using constexpr.
#include <iostream>
#include <array>
using namespace std;
constexpr long long factorial(int n) {
long long result = 1;
for (int i = 2; i <= n; i++)
result *= i;
return result;
}
template<size_t... Is>
constexpr auto makeFactTable(index_sequence<Is...>) {
return array<long long, sizeof...(Is)>{factorial(Is)...};
}
constexpr auto factTable = makeFactTable(make_index_sequence<13>{});
int main() {
for (int i = 0; i <= 12; i++)
cout << i << "! = " << factTable[i] << endl;
return 0;
}Challenge 4: Transform and Filter with Lambdas (Functional Pipeline)
HardGiven a vector of integers, use STL algorithms with lambdas to: (1) filter out odd numbers, (2) square the remaining even numbers, (3) sum the results. Use erase-remove idiom, transform, and accumulate.
Sample Input
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Sample Output
Even numbers: 2 4 6 8 10
Squared: 4 16 36 64 100
Sum of squares: 220
Use lambdas with remove_if, transform, and accumulate. No manual loops.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Step 1: Remove odd numbers
v.erase(remove_if(v.begin(), v.end(), [](int x) { return x % 2 != 0; }), v.end());
cout << "Even numbers: ";
for (auto x : v) cout << x << " ";
cout << endl;
// Step 2: Square each element
transform(v.begin(), v.end(), v.begin(), [](int x) { return x * x; });
cout << "Squared: ";
for (auto x : v) cout << x << " ";
cout << endl;
// Step 3: Sum
auto sum = accumulate(v.begin(), v.end(), 0);
cout << "Sum of squares: " << sum << endl;
return 0;
}Challenge 5: Optional-Based Safe Division with Error Handling
MediumWrite a function safeDivide that returns optional. Return nullopt for division by zero. Chain multiple operations and handle the optional results.
Sample Input
safeDivide(10, 3), safeDivide(10, 0), safeDivide(100, 4)
Sample Output
10 / 3 = 3.33333
10 / 0 = error (division by zero)
100 / 4 = 25
Use std::optional. No exceptions or error codes.
#include <iostream>
#include <optional>
using namespace std;
optional<double> safeDivide(double a, double b) {
if (b == 0) return nullopt;
return a / b;
}
void printResult(double a, double b) {
auto result = safeDivide(a, b);
cout << a << " / " << b << " = ";
if (result)
cout << result.value() << endl;
else
cout << "error (division by zero)" << endl;
}
int main() {
printResult(10, 3);
printResult(10, 0);
printResult(100, 4);
return 0;
}Challenge 6: Generic Sorting with Concepts (C++20)
HardWrite a generic sortAndPrint function constrained by a concept that requires the type to be sortable (has begin/end iterators and elements support <). Demonstrate with vectors of int, string, and double.
Sample Input
vector<int>{5,3,1}, vector<string>{"Kiran","Arjun","Priya"}, vector<double>{3.14,1.41,2.72}
Sample Output
1 3 5
Arjun Kiran Priya
1.41 2.72 3.14
Use C++20 concepts and requires clause.
#include <iostream>
#include <vector>
#include <algorithm>
#include <concepts>
#include <string>
using namespace std;
template<typename C>
concept Sortable = requires(C c) {
{ c.begin() } -> input_or_output_iterator;
{ c.end() } -> input_or_output_iterator;
requires totally_ordered<typename C::value_type>;
};
void sortAndPrint(Sortable auto& container) {
sort(container.begin(), container.end());
for (const auto& x : container) cout << x << " ";
cout << endl;
}
int main() {
vector<int> ints = {5, 3, 1};
vector<string> strs = {"Kiran", "Arjun", "Priya"};
vector<double> dbls = {3.14, 1.41, 2.72};
sortAndPrint(ints);
sortAndPrint(strs);
sortAndPrint(dbls);
return 0;
}Need to Review the Concepts?
Go back to the detailed notes for this chapter.
Read Chapter NotesWant to learn C++ with a live mentor?
Explore our C++ Masterclass