5.2.1 · D5C++ Programming
Question bank — C++ as superset of C — key additions
Quick vocabulary refresher, so no symbol appears un-earned:
- superset — language is a superset of if (almost) every valid program is also a valid program. C++ is a near-superset of C.
- invariant — a rule about an object that must always stay true (e.g. "a bank balance is never set to garbage from outside").
- heap — the region of memory you request at runtime and must release yourself; the opposite of the automatic stack.
- dispatch — deciding which function actually runs for a call. Static dispatch is decided at compile time, dynamic (
virtual) at runtime. - nullptr — C++'s dedicated "points at nothing" pointer value (the modern replacement for
NULL); a pointer holding it refers to no object. - undefined behaviour (UB) — code the language rules give no meaning to, so the compiler may do anything: crash, corrupt data, or appear to work. It is a bug even when it seems harmless.
True or false — justify
True or false: Every valid C program compiles unchanged as a C++ program.
False — C++ is a near-superset only. Stricter rules (no implicit
void*→T*, more reserved keywords, tighter type checks) reject a small slice of otherwise-fine C code.True or false: int* p = malloc(4); compiles in both C and C++.
False — legal in C thanks to implicit
void*→int* conversion, but a compile error in C++, which demands an explicit cast (int*)malloc(4). See new and delete vs malloc and free.True or false: Writing int new = 5; is a portable way to name a variable.
False —
new is a C++ keyword, so this compiles in C but is an error in C++. C++ has more reserved words (new, class, template, try…) than C.True or false: A struct in C++ is identical in every way to a struct in C.
False — a C++
struct can have member functions, constructors, access control, and inheritance; its only difference from a C++ class is that members default to public instead of private.True or false: Using a class instead of a plain struct always makes the program slower.
False — non-
virtual member calls compile to the same machine code as free functions. "You don't pay for what you don't use"; cost appears only when you ask for virtual dynamic dispatch.True or false: new is essentially a type-aware wrapper around malloc.
False in behaviour — beyond allocating memory,
new calls the constructor and delete calls the destructor, while malloc/free never touch constructors or destructors.True or false: A reference in C++ is just a pointer with nicer syntax.
Mostly false — a reference cannot be null and cannot be reseated to another object after initialisation, so it removes a whole class of pointer bugs. See Pointers vs References.
True or false: Templates make the executable larger because one definition handles all types.
False premise — the compiler stamps out a separate version per type actually used (code duplication), so genericity is zero-runtime-overhead but not necessarily zero-code-size. See Templates and Generic Programming.
True or false: std:: in front of vector or cout is decoration you can always drop.
False —
std is a namespace; dropping it only works after a using declaration, and blanket using namespace std; risks name collisions.True or false: Function overloading and function templates solve the exact same problem.
Partly false — overloading gives different bodies for chosen parameter lists; a template gives one body the compiler reuses for many types. They overlap but are not interchangeable.
True or false: char* s = "hello"; is fine in both C and C++.
False — a string literal is read-only, so C++ requires
const char* s = "hello";. The non-const form compiles in C (with a deprecation) but is an error in modern C++.True or false: struct Point p = { .x = 1, .y = 2 }; (C99 designated initializers) works identically in C and C++.
Mostly false — this C99 feature compiles in C but was rejected in C++ until C++20, and even C++20 forbids reordering fields, so pre-C++20 code fails.
Spot the error
Spot the error: class Account { int balance = 0; void deposit(int x){ balance += x; } }; then Account a; a.deposit(10);
deposit is private (class members default to private), so a.deposit(10) is illegal from outside. Add a public: label above deposit. See Classes and Objects in C++.Spot the error: int* p = new int; free(p);
Mixing allocators — memory from
new must be released with delete, not free. Pairing new↔free is undefined behaviour.Spot the error: int* p = (int*)malloc(sizeof(int)); delete p;
Same crime the other way —
malloced memory must go to free, never delete. delete would also try to run a destructor that was never matched by a constructor.Spot the error: #define MAX(a,b) ((a)>(b)?(a):(b)) used as MAX(i++, j).
The macro pastes
i++ twice, so it may increment i two times. A template<typename T> T maxv(T a,T b) is a real function that evaluates each argument once.Spot the error: int& r; declared with no initialiser.
A reference must be bound at the moment it is created — there is no "null" or "later" reference. Write
int x; int& r = x;.Spot the error: throw used but no surrounding try/catch anywhere in the program.
This is legal, not a syntax error: an uncaught exception simply calls
std::terminate and aborts. A catch is required only when you intend to recover from the error. See Exception Handling try-catch-throw.Spot the error: struct S {}; S x; a programmer claims this needs struct S x; in C++.
In C++ the tag
S is already a type name, so S x; is correct; the extra struct keyword is required only in classic C.Spot the error: void f(int n){ int a[n]; } copied from C99 into a C++ file.
int a[n] is a variable-length array (VLA), a C99 feature not in standard C++. Use std::vector<int> a(n); instead. See The STL — vector, map, string.Spot the error: a C89-style file uses f(x); where f was never declared, then compiled as C++.
C89's implicit-
int rule let an undeclared function default to returning int; C++ forbids this, so you must declare or include f before calling it.Why questions
Why did C++ add private access when C structs already grouped data?
Grouping alone doesn't protect: any C code can corrupt
acc->balance. private makes the compiler enforce the invariant that data changes only through approved methods.Why prefer references over pointers for pass-by-reference?
References auto-dereference (no noisy
*/&) and can never be null or reseated, eliminating a common family of pointer mistakes while reading like a plain variable.Why do namespaces exist when C already let you name things freely?
C has a single global namespace, so two libraries both defining
init() collide and neither links cleanly. Namespaces let net::init() and gfx::init() coexist.Why are exceptions considered safer than checking return codes?
They separate the error path from the happy path, so error handling can't be silently forgotten and normal logic stays uncluttered by status-code checks.
Why does the phrase "don't pay for what you don't use" matter for adoption?
It reassures C programmers that adding C++ abstractions costs nothing at runtime unless invoked, so C++ keeps C's low-level speed while offering optional safety.
Why is stronger type checking (e.g. banning implicit void*→T*) an addition, not a loss?
It converts silent runtime pointer bugs into loud compile-time errors, catching mistakes earlier at the price of a little verbosity.
Why does C++ force const on a string literal's pointer type?
Literals live in read-only memory; typing them as
const char* makes any attempt to modify them a compile error rather than runtime undefined behaviour.Edge cases
Edge case: what happens if you call delete twice on the same pointer?
Double-free is undefined behaviour (often a crash or heap corruption). Set the pointer to
nullptr after the first delete, or use a container/smart pointer.Edge case: does delete on a nullptr crash?
No —
delete nullptr; is defined to do nothing, which is why nulling pointers after freeing them is a safe habit.Edge case: what does a template do if a type used inside it (e.g. a > b) has no matching operator?
Compilation fails at instantiation with an error, not at runtime — the template is only fully checked once you supply a concrete type.
Edge case: can a C++ program still call plain C functions and use malloc/printf?
Yes — C++ keeps all of C's low-level tools; you can freely mix them, though pairing
malloc↔free and new↔delete correctly is your responsibility. See Compilation Model — C vs C++.Edge case: is a class with everything public and no methods effectively a C struct?
Functionally yes — an all-
public, method-free class behaves like a plain data struct, which is exactly what a C++ struct defaults to.