C++ is a mid-level language combining high-level abstractions (classes, inheritance, templates) with low-level memory control (pointers, dynamic allocation). Core concepts include variables, functions, references, operators, and object-oriented features like encapsulation and polymorphism. Memory handling covers stack vs heap allocation, pointers, dynamic memory (new/delete), deep vs shallow copies, and smart pointers.
1. How do you free memory allocated with new?
Use delete for single values, and delete[] for arrays:
2. What is the difference between new and malloc()?
Following are the major difference between new and malloc()
new | malloc() |
|---|
| An operator which performs an operation | A function that returns and accepts values |
| Calls the constructors | Cannot call a constructor |
| Returns the exact data type | Returns void* |
3. What happens if we change pointer ?
If you pass a pointer by value but forget to use dereferencing, changes won’t reflect.
Code:
4. How internally delete and delete[] works in cpp?
delete and delete[] deallocate memory obtained from new and new[].
- For single objects, delete calls the destructor (if any) and then releases memory using operator delete.
- For arrays, delete[] calls the destructor for each element and then uses operator delete[] to free the memory block.
The compiler typically keeps track of the number of elements internally (implementation-defined).
Note: The actual destructor calls and memory release are handled automatically by the compiler/runtime; programmers should never explicitly invoke ptr->~T() before delete.
Example of delete:
Example of delete[]:
Note: If the object is a primitive type (int, char), destructors aren't needed.
5. How we can make custom delete?
You can overload operator delete or operator delete[] in your class:
6. What happens if you return a pointer to a local variable from a function?
The pointer becomes dangling because the variable’s lifetime ends when the function exits. Accessing it causes undefined behavior.
7. Demonstrate shallow vs deep copy in C++ with memory implications.
OutputShallow Copy:
a = 20, b = 20
Deep Copy:
x = 10, y = 30
- Shallow Copy: Both pointers (a and b) refer to the same memory. Updating one updates the other.
- Deep Copy: A new memory block is allocated (y), so changes don’t affect the original (x).
8. Explain why delete cannot be used for arrays with demonstration?
- If memory is allocated using new[], it must be freed using delete[].
- Using plain delete on an array leads to undefined behavior because the compiler will not correctly destroy all elements.
- For simple data types (like int), it may look like it works, but for objects with destructors, only the first element may be destroyed, leaving the rest as a memory leak.
- Rule of thumb: 1) new → delete, 2)new[] → delete[]
Example:
9. Show why base class destructors should be virtual.?
- If the base class destructor is not virtual, deleting a derived object through a base pointer calls only the base destructor.
- This skips cleanup of the derived class → can cause memory leaks or incomplete destruction.
- Making the destructor virtual ensures the derived destructor is called first, then the base destructor → proper cleanup.
Example:
OutputBase constructor
Derived constructor
Base destructor
10. How do auto and decltype improve type safety? Show with example.
- auto deduces the type from the initializer, ensuring the variable always matches the assigned expression and avoiding mismatched type declarations.
- decltype deduces the type from an expression or variable, ensuring consistency in return types and variable declarations.
- Together, they improve type safety by letting the compiler handle type correctness, especially in complex or generic code.
Example:
12. Show how mutable allows changing internal state even in a const object?
- Normally, a const object in C++ cannot modify its data members.
- If a data member is marked mutable, it can still be changed even inside a const object.
- This is useful when some internal details (like caching, counters, or logs) need to change without affecting the logical state of the object.
Example:
OutputAccess count = 1
Access count = 2
Even though obj is const, the mutable member (accessCount) can still be changed.
13. How does pointer arithmetic lead to undefined behavior if misused?
- Pointer arithmetic allows direct memory access, but accessing out-of-bounds memory is undefined.
- Compiler may not throw errors, but program may crash or show garbage.
Example cases:
- Incrementing past the end of an array.
- Decrementing before the start of an array.
- Adding large offsets that go far beyond allocated memory.
Code Example:
14. Demonstrate difference in memory layout and access.
- int* arrOfPtrs[3]: An array of 3 pointers to int. Each pointer can point to separate memory locations (may be on stack or heap).
- int (*ptrToArr)[3]: A single pointer to an array of 3 ints. In the example, new int[1][3] allocates a block of 3 contiguous ints on the heap, and ptrToArr points to it.
So the difference is in layout:
- Array of pointers: multiple independent ints, not guaranteed contiguous.
- Pointer to array: one block of contiguous memory.
Example: