1. What does this string comparison print?
#include <iostream>
#include <string>
int main() {
std::string s1 = "hello";
std::string s2 = "hello";
const char *c1 = "hello";
const char *c2 = "hello";
std::cout << (s1 == s2) << "\n";
std::cout << (c1 == c2) << "\n";
return 0;
}
Output:
1
1
std::string == compares content — two equal strings are true. But c1 == c2 compares the pointer addresses of the two literals. Whether the compiler merges identical string literals is implementation-defined, so this is exactly the kind of comparison you must never rely on: on this compiler the literals are merged and the addresses are equal, giving 1 — but on another compiler the result could be 0. Never use == on const char* to compare text — use std::string or strcmp.
2. What does this integer division print?
#include <iostream>
int main() {
std::cout << 7 / 2 << "\n";
std::cout << -7 / 2 << "\n";
std::cout << 7 % 3 << "\n";
std::cout << -7 % 3 << "\n";
return 0;
}
Output:
3
-3
1
-1
Since C++11, integer division truncates toward zero: 7 / 2 is 3, -7 / 2 is -3. The % result takes the sign of the dividend: 7 % 3 is 1, -7 % 3 is -1. This differs from Python’s floor division and is the standard C++ interview expectation.
3. What does this boolean output print?
#include <iostream>
int main() {
bool a = true;
bool b = false;
std::cout << a << " " << b << "\n";
std::cout << std::boolalpha;
std::cout << a << " " << b << "\n";
return 0;
}
Output:
1 0
true false
By default, std::ostream prints bool as 1/0. With the std::boolalpha manipulator, it prints true/false. The state change persists for the rest of the stream. This default 1/0 output is a frequent trick question.
4. What does this character literal print?
#include <iostream>
int main() {
std::cout << sizeof('a') << "\n";
std::cout << sizeof("hello") << "\n";
return 0;
}
Output:
1
6
Unlike C, in C++ a character literal 'a' has type char, so sizeof('a') is 1 (in C it would be sizeof(int) = 4). "hello" is a const char[6] including the null terminator, so sizeof is 6. The C-vs-C++ sizeof('a') difference is a classic interview question.
5. What does this reference-vs-value print?
#include <iostream>
void set10(int x) { x = 10; }
void set10ref(int &x) { x = 10; }
int main() {
int a = 1;
int b = 1;
set10(a);
std::cout << a << " ";
set10ref(b);
std::cout << b << "\n";
return 0;
}
Output:
1 10
Passing by value copies the argument, so set10(a) does not change a — prints 1. Passing by reference lets the function mutate the caller’s variable, so set10ref(b) changes b to 10. The & reference parameter is the C++ mechanism C emulates with pointers.
6. What does this default-argument virtual call print?
#include <iostream>
class Base {
public:
virtual void show(int i = 10) {
std::cout << "Base " << i << "\n";
}
};
class Derived : public Base {
public:
void show(int i = 20) override {
std::cout << "Derived " << i << "\n";
}
};
int main() {
Base *p = new Derived();
p->show();
delete p;
return 0;
}
Output:
Derived 10
Virtual dispatch calls Derived::show (dynamic type), but the default argument is chosen from the static type (Base), so i is 10. The result is the famous “Derived function, Base default” — Derived 10. Never use different defaults in overridden virtual functions.
7. What does this destructor order print?
#include <iostream>
struct A {
~A() { std::cout << "A "; }
};
struct B {
~B() { std::cout << "B "; }
};
int main() {
A a;
B b;
std::cout << "end ";
return 0;
}
Output:
end B A
Local objects are destroyed in reverse order of construction at the end of the block. a is constructed first, then b, so at scope exit b is destroyed first (prints B), then a (prints A). The "end " prints before any destructor. Destructor order is a staple C++ interview question.
8. What does this stack-vs-heap sizeof print?
#include <iostream>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
std::cout << sizeof(arr) << "\n";
std::cout << sizeof(p) << "\n";
return 0;
}
Output:
20
8
sizeof(arr) is the full array: 5 * sizeof(int) = 20. sizeof(p) is the pointer size, 8 on a 64-bit platform. arr is the actual array, but when passed to a function or stored in a pointer it decays to int*, losing its size. This array-vs-pointer sizeof distinction is constantly tested.
9. What does this function-overload print?
#include <iostream>
void f(int) { std::cout << "int\n"; }
void f(double) { std::cout << "double\n"; }
void f(char) { std::cout << "char\n"; }
int main() {
f(5);
f(5.0);
f('a');
return 0;
}
Output:
int
double
char
Overload resolution picks the exact type match first. 5 is int, 5.0 is double, 'a' is char. The compiler prefers an exact match over a conversion, so each call reaches the right overload without ambiguity.
10. What does this integer-overload print?
#include <iostream>
void f(int) { std::cout << "int\n"; }
void f(double) { std::cout << "double\n"; }
int main() {
f(3.14f);
f('x');
return 0;
}
Output:
double
int
3.14f is a float; neither overload matches exactly, so the compiler uses the promotion float → double. 'x' is a char, which promotes to int. When no exact match exists, integral promotions (char→int, float→double) win over other conversions.
11. What does this increment-overload print?
#include <iostream>
int main() {
int i = 5;
std::cout << i++ << " ";
std::cout << i << " ";
std::cout << ++i << " ";
std::cout << i << "\n";
return 0;
}
Output:
5 6 7 7
i++ yields the old value 5 and then increments to 6. ++i increments to 7 and yields 7. The output is 5 6 7 7. Each expression is a separate statement here, so the order is fully well-defined.
12. What does this ternary print?
#include <iostream>
int main() {
int x = 10;
std::cout << (x > 5 ? "big" : "small") << "\n";
std::cout << (x > 5 ? 100 : 200) << "\n";
return 0;
}
Output:
big
100
The ternary cond ? a : b evaluates the condition and returns only the chosen branch. x > 5 is true, so it prints "big" and 100. The unselected branch is never evaluated — useful for lazy evaluation and avoiding side effects.
13. What does this const-correctness print?
#include <iostream>
int main() {
const int x = 5;
const int *p = &x;
int y = 10;
std::cout << *p << "\n";
p = &y;
std::cout << *p << "\n";
return 0;
}
Output:
5
10
const int *p is a pointer to a const int — you cannot modify *p through it, but the pointer itself can be reassigned. So p = &y is legal and *p prints 10. A int *const (const pointer) would be the opposite: can’t reassign the pointer, but can modify the pointee.
14. What does this constructor-order print?
#include <iostream>
class Base {
public:
Base() { std::cout << "Base "; }
~Base() { std::cout << "~Base "; }
};
class Derived : public Base {
public:
Derived() { std::cout << "Derived "; }
~Derived() { std::cout << "~Derived "; }
};
int main() {
Derived d;
std::cout << "end ";
return 0;
}
Output:
Base Derived end ~Derived ~Base
Construction is base first, then derived (base subobject initialized before the derived body runs). Destruction is the exact reverse: derived destructor first, then base. So we get Base Derived, then end, then ~Derived ~Base. This order is a guaranteed interview favorite.
15. What does this copy-construction print?
#include <iostream>
struct Vec {
int x, y;
Vec(int a, int b) : x(a), y(b) {}
};
int main() {
Vec v1(3, 4);
Vec v2 = v1;
std::cout << v2.x << " " << v2.y << "\n";
std::cout << (v1.x == v2.x) << "\n";
return 0;
}
Output:
3 4
1
Vec v2 = v1 invokes the implicit copy constructor, which copies each member. v2 gets x = 3, y = 4, and the memberwise copy makes v1.x == v2.x true. For a simple aggregate like this the implicit copy is exactly what you’d expect.
Premium Content
Unlock Output Questions - Part 1 and all premium lessons with a subscription.
From ₹199.99/year — See plans