← Back to C++ Course | Chapter 17: Advanced C++ | Lesson 17 of 17

C++ Interview Questions Advanced

Smart Pointers and RAII

Smart pointers apply RAII (Resource Acquisition Is Initialization) to dynamic memory: std::unique_ptr enforces single ownership and frees its object automatically when it goes out of scope, while std::shared_ptr allows multiple owners via reference counting -- both eliminate the need to remember a manual delete.

Example: Smart Pointers and RAII

cpp
#include <iostream>
#include <memory>

int main() {
	std::unique_ptr<int> ptr = std::make_unique<int>(5);
	std::cout << *ptr << std::endl;
	return 0;
}

Move Semantics and rvalue references

Move semantics lets an object's internal resources -- like a heap buffer -- be transferred from a temporary into a new object via pointer reassignment, rather than performing a full deep copy. This is what makes returning large objects from functions cheap in modern C++.

Example: Move Semantics and rvalue references

cpp
#include <iostream>
#include <vector>

int main() {
	std::vector<int> source = {1, 2, 3};
	std::vector<int> target = std::move(source);
	std::cout << target.size() << std::endl;
	return 0;
}

Virtual Destructors

A base class intended to be deleted through a base-class pointer must declare its destructor virtual; otherwise, deleting a derived object through a base pointer only runs the base class's destructor, skipping the derived class's cleanup and leaking any resources it owns.

Example: Virtual Destructors

cpp
#include <iostream>

class Base {
public:
	virtual ~Base() { std::cout << "Base destroyed" << std::endl; }
};

class Derived : public Base {
public:
	~Derived() { std::cout << "Derived destroyed" << std::endl; }
};

int main() {
	Base *b = new Derived();
	delete b;
	return 0;
}

SFINAE and Concepts

SFINAE ("Substitution Failure Is Not An Error") is a template-metaprogramming technique where an invalid template substitution is silently discarded from overload resolution rather than causing a compile error, letting templates constrain which types they accept. C++20 Concepts formalize this into readable, explicit syntax.

Example: SFINAE and Concepts

cpp
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
show(T value) {
	std::cout << "Integral: " << value << std::endl;
}

int main() {
	show(5);
	return 0;
}

Perfect Forwarding and std::forward

Perfect forwarding, using std::forward inside a template function that takes universal references (T&&), preserves whether each argument was originally an lvalue or an rvalue as it's passed along to another function -- essential for generic wrapper functions that shouldn't accidentally force an unnecessary copy.

Example: Perfect Forwarding and std::forward

cpp
#include <iostream>
#include <utility>

void process(int &x) { std::cout << "lvalue" << std::endl; }
void process(int &&x) { std::cout << "rvalue" << std::endl; }

template <typename T>
void wrapper(T &&arg) {
	process(std::forward<T>(arg));
}

int main() {
	int a = 5;
	wrapper(a);
	wrapper(10);
	return 0;
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.