Meters(double) is a non-explicit single-argument constructor, so the compiler silently converts 3.5 into a Meters to call twice. 3.5 × 2 = 7 (printed as 7).
int& f() { int x = 5; return x; }: x dies when f returns, so the reference points at a dead stack slot (g++ warns: reference to local variable 'x' returned). Returning by value, a static local, or a unique_ptr are all safe.
Why is returning the address of a local variable a bug?
The local lives in the function's stack frame, which is reclaimed when the function returns. The returned address then points to memory that's no longer valid — a dangling pointer — so using it is undefined behaviour.
Because it would need two user-defined conversions: const char* -> std::string -> Entity. The compiler allows at most one user-defined conversion in a chain. Entity e = std::string("Anup"); works because that's only one.
True or false: the compiler-generated copy constructor copies the data that a pointer member points to.
False. It copies member by member, so a pointer member's address is copied (a shallow copy): both objects share one buffer, which leads to a double-free. A deep copy needs your own copy constructor.
This version returns Counter by value instead of by reference. What does it print now?
C++
struct Counter {
int n = 0;
Counter add(int k) { n += k; return *this; } // returns a copy
};
intmain() {
Counter c;
c.add(1).add(2).add(3);
std::cout << c.n;
}
Returning *thisby value hands back a copy. Only the first add(1) changes c; .add(2) and .add(3) change temporary copies that are thrown away. So c.n is 1.
Is the ternary a statement or an expression, and why does that matter?
An expression — it produces a value. That's why it can be used inline where a value is needed (initializing a variable or a const, a return, a function argument), which an if/else statement can't do.
free/delete are given only p — how do they know where the header is and how big the block is?
The header offset is a fixed constant compiled into the allocator, so it computes p - headerSize to reach the header from just p. The block size is stored inside that header, so it reads it once the header is found.
True or false: if a member has a default initializer (int a = 0;) and is also in the member initializer list, the list's value is used.
True. The list takes precedence: the default initializer is simply not used for that constructor (the member is initialized once, with the list's value).
Any two of: you can't invent new operators or change their precedence/arity; at least one operand must be a user-defined type (int+int can't be redefined); and ::, ., .*, ?:, sizeof can't be overloaded at all.
How do you pass an argument to a base class constructor?
In the derived class's initializer list: Derived(int x) : Base(x) {}. It's the only place you can — omit it and the base's default ctor is called (error if none). Needed even inside a default constructor.
Which of these leak memory or use a dangling pointer? Select all that apply.
Losing the only pointer to a new object without deleteleaks it, and calling through a pointer after delete uses a dangling pointer. Pointing at a live stack object in the same scope is fine, and make_unique cleans up by itself.
auto a = std::make_shared<int>(5);
std::cout << a.use_count();
{
auto b = a;
std::cout << a.use_count();
}
std::weak_ptr<int> w = a;
std::cout << a.use_count();
One owner: count 1. Inside the block b shares ownership: 2. b dies at the closing brace: back to 1. A weak_ptr observes without owning, so the count stays 1.
Why can you use -> on a smart pointer even though it's an object, not a raw pointer?
Because the smart pointer overloads operator-> (and operator*). So p->method() calls p.operator->() to get the raw pointer, then applies -> to that — letting an object behave like a pointer.
Rule of Three: if a class needs a custom destructor, it almost certainly also needs a custom copy constructor and copy assignment operator (all manage the same resource). Rule of Five (C++11) adds a move constructor and move assignment for efficiency.
What are the two places an object can live, and how does each affect its lifetime?
The stack and the heap. A stack object (Entity e;) has automatic lifetime — destroyed when it leaves scope, with its destructor called for you. A heap object (new Entity) has manual lifetime — it lives until you delete it, so it can outlive the scope (but leaks if you forget).
v[i] does no bounds checking — an out-of-range index is undefined behaviour. v.at(i)checks the index and throws std::out_of_range if it's invalid (safer, slightly slower).