C++ Concepts
Last updated on
13 min read
Table of Contents
- STL Notes
- General
- Int, Float, Double
- Array
- Char
- String
- Sequential Containers
- Vector
- List
- Deque
- Array
- Forward List
- Container Adapters
- Stack
- Queue
- Priority Queue
- Associative Containers
- Set
- Multiset
- Map
- Multimap
- Unordered Containers
- Unordered Set
- Unordered Multiset
- Unordered Map
- Unordered Multimap
- Others
- Pair
- Math
- Random
- Pointers
- Operator Overloading
- Exception Handling
- Generics
- Lambda
- Multi Threading
- Functors
- OOPS
- Snippets
- Interesting Questions
STL Notes
General
- Import all containers (vector, stack, queue etc.)using -
#include <bits/stdc++.h>
- long and int are same in c++. They both take 4 bytes only. If you want to store 8 bytes then use long long
- A c++ project contains .h/.hpp and .cpp files.
- After compiling your library, you can link it in your project either using static linking or dynamic linking. Static linking includes uses .lib files and the output would contain the library files internally linked. In dynamic linking (.dll), it only used dll files and are externally linked using a absolute path. Static linking involves combining all necessary library routines and external references into a single executable file at compile-time. Dynamic linking involves linking external libraries and references at runtime, when the program is loaded and executed.
- A macro is a preprocessor directive defined in the source code that is replaced by its value by the preprocessor before compilation. Eg.
#define
sizeof(int or float or struct or class etc)
returns the size of a variable
Int, Float, Double
- Convert from int to float -
float(intValue)
- Convert from int to double -
double(intValue)
- Convert from double to int -
int(doubleValue)
- INT_MAX, INT_MIN for extreme ends of int value
- Optional separators ’ for integer literals. For example - 1’234’567 for better readability
- Hexadecimal numbers can be represented as - oxAE12
- Binary numbers can be represented as 0b1101
Array
- Declare an array -
int arr[26] = {0};
- You cannot give a dynamic size value to an array in c++. Array size needs to be provided during the compile time itself
Char
- Create a char -
char A = 'a';
- Get ascii value of char -
int('a');
- Convert ascii value to char -
char(53);
- Convert char number to int -
int(ch - '0');
- Boolean methods for checking the type of character -
isalpha(c)
andisalnum(c)
andisdigit(c)
andispunct(c)
tolower(c)
andislower(c)
toupper(c)
andisupper(c)
String
- .size() and .length() methods are the same
- string concatenation can be done using
str1 + str2
; - Convert int to string using -
to_string(intValue)
- Convert string to int using -
stoi(str);
orint (string str, position = 0, base = 10);
position is 0 and base is 10 as default. Also can useatoi
with similar behavior - Get substring -
str.substr(index, len);
- Find first occurrence of a character -
str1.find(searchString)
- returns index value - Append a string -
str1 + str2
orstr1.append(str2);
- Replace -
str1.replace(index, size, str2);
- Insert -
str1.insert(index, str2);
- Erase -
str1.erase(index, len);
- Repeat a char n times in a string -
string(5, '.')
- Push a string or char at end
str1.push_back('c')
- Pop the last character from the end
str1.pop_back()
Sequential Containers
Vector
- Create a vector -
vector<int> output;
- Create a vector of given size -
vector<int> output(nums.size());
- Push data to vector array -
vectorArr.push_back(value)
- Pop last item from vector array -
vectorArr.pop_back();
- Sort in reverse order -
sort(arr.begin(), arr.end(), [](int i, int j) { return i > j; });
- Reverse a vector -
reverse(arr.begin(), arr.end())
- Size of vector array -
vectorArr.size()
- Sort a vector array -
sort(vectorArr.begin(), vectorArr.end())
- Sort in reverse -
reverse(arr.begin(), arr.end(0));
- Custom sorting a vector using comparator
sort(vect.begin(), vect.end(), [](int value1, int value2){
return value1 < value2;
})
- Find if an element exists
// Using find
if(find(v.begin(), v.end(), target) != v.end()){
// Element found
}
// Using count
if(count(v.begin(), v.end(), target) > 0){
// Element found
}
- Partial sort - If you want to sort only the first two elements of the array then
// This will sort the array in increasing order but only the first two elements are sorter
partial_sort(arr.begin(), arr.begin() + 2, arr.end());
// This will sort the array in decreasing order but only the first two elements are sorted
partial_sort(arr.begin(), arr.begin()+2, arr.end(), greater<int>());
- By default vectors are passed by value. So, if you make any changes to the vector in inside the function call, it won’t affect the actual vector from which is was passed. If you want to pass by reference use
methodName(vector<int> &nums)
in the function declaration. Best explanation is given here - https://www.geeksforgeeks.org/passing-vector-function-cpp/
List
- Doubly linked list
- The difference between list and deque is that, deque allows only data to be added or removed at the front and back. But list allows you to insert and erase data at any point of the list.
Deque
front()
back()
push_front()
push_back()
pop_front()
pop_back()
insert()
size()
begin()
andend()
Array
Forward List
Container Adapters
Stack
- Create a stack -
stack<int> st;
- Push an item -
st.push(val);
- Pop an item -
st.pop()
note: it will only pop the value, it will not return any value - Peek the top of the stack -
st.top();
- Size of stack -
st.size();
- Check if empty -
st.empty();
Queue
- Create a queue -
queue<int> que
- Enqueue -
queue.push(val)
- Dequeue -
queue.pop()
Note: This will only pop the element won’t return the popped value. Use front() before popping to get the value - Front -
queue.front()
- Value of the oldest item in the queue will be returned - Back -
queue.back()
- Value of the latest item pushed will be returned - Size -
queue.size()
- Check if empty -
queue.empty()
Priority Queue
- Create a priority queue as max heap -
priority_queue<int>
- Creates a max heap and it returns the top value in the queue - Create a priority queue as min heap -
pq<int, vector<int>, greater<int>>
- Pops the smallest value from the heap.vector<int>
is the internal container used to store these elements, since priority queues are container adopters and not containers in itself.greater<int>
is a custom comparison function which determines how the elements are stored in. - Top -
pq.top()
- returns top element - Pop an element -
pq.pop()
- removes the top element - Push an element -
pq.push(val)
- pushes an element - Check if empty -
pq.empty()
- Return size -
pq.size()
- Complex priority queue initialization -
priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, greater<pair<int, pair<int, int>>>> pq;
Associative Containers
Set
- Create a set -
set<int> set;
- Create a set in descending order -
set<int, greater<int>> set;
- Insert in set -
set.insert(val)
- Erase a value -
set.erase(val);
- Find if exists -
set.find(val) != set.end();
- Clear all values -
set.clear();
- Check if empty -
set.empty();
- Get size -
set.size();
- Set and unordered set are pretty similar, but if the order doesn’t matter for you, then go for unordered_set
unordered_set
can also be used which has similar functions with different underlying implementations and time complexities
Multiset
Map
- Create a map -
map<int, string> map;
- Create a map with default value -
unordered_map<char, char> map{{'one','1'}, {'two', '2'};
- Insert -
map[key] = val;
ormap.insert({key, val});
- Erase a value -
map.erase(key);
- Find if exists -
map.find(key) != set.end();
- Get size -
map.size();
- Clear all values -
map.clear();
unordered_map
can also be used which has similar functions with different underlying implementations and time complexities- Check if empty -
map.empty();
- Looping through map
for(auto item: map){
cout << item.first << " - " << item.second;
}
OR
for(auto [key, val]: map){
cout << key << " - " << val;
}
Multimap
Unordered Containers
Unordered Set
Unordered Multiset
Unordered Map
Unordered Multimap
Others
Pair
- Define a pair -
pair<datatype1, datatype2> pair_name;
- Initialize a pair -
pair_name(val1, val2);
ormake_pair(val1, val2)
orpair_name = {val1, val2}
- Get values using -
pair_name.first
andpair_name.second
Math
- Max and Min -
max(num1, num2)
,min(num1, num2)
- Get max value in a vector -
*max_element(arr.begin(), arr.end())
. The function returns a iterator. To get the actual max value use * to deference it - Square root -
sqrt(double)
, Cube root -cbrt(double)
- Round off -
round(num)
- Log -
log(num)
- Absolute -
abs(int)
,fabs(double)
- Power -
pow(double, double)
- Floor and ceil -
floor(double)
,ceil(double)
- Trigonometry -
sin(x) ,cos(x), tan(x),
Random
- To get a random number between 0 to 4 inclusive -
rand() % 5
orrand() % (high + 1)
- To get a random number between 11 to 20 inclusive -
low + (rand() % (high+1-low))
Pointers
int num = 10;
// Initializes a num variableint *ptr;
// Creates a pointer variable to store the pointerptr = &num
// & gets the memory location of the num variable and assigns it to pointercout << ptr << endl;
// It prints the location of the pointer the actual memory addresscout << *ptr << endl;
// It prints the actual value stored, that is the value 10sw
Operator Overloading
- Operator overloading is a feature in C++ that allows operators such as
+
,-
,*
,/
,=
, and many others to be redefined for user-defined classes - General syntax -
returnType operator symbol(arguments) { function body }
- Simple example for overloading + operator
class Complex {
private:
float real;
float img;
public:
// constructor
Complex(float r = 0.0, float i = 0.0) : real(r), img(i) {}
// overload + operator
Complex operator+(const Complex& obj) {
Complex temp;
temp.real = real + obj.real;
temp.img = img + obj.img;
return temp;
}
};
int main() {
Complex c1(2.5, 3.0), c2(1.6, 2.0);
Complex c3 = c1 + c2;
return 0;
}
- Different ways to overload an operator
- As a member function - Defined inside the class
- As Friend (non-member) function - Defined outside the class
// As member function
Complex operator+(const Complex& other) {
// function body
}
// As (Friend) non-member function
class Complex {
Public:
Complex(double real, double image) : real(real), imag(imag) {}
// Declare the '+' operator as a friend
friend Complex operator+(const Complex& c1, const Complex& c2);
Private:
double real, imag;
};
// Define the '+' operator using a friend function
Complex operator+(const Complex& c1, const Complex& c2) {
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
- Operator overloading in case of
<<
operator
class Point {
private:
int x, y;
public:
Point(int x, int y) : x(x), y(y) {}
};
ostream& operator<<(ostream& out, const Point& p) {
out << "(" << p.x << ", " << p.y << ")";
return out;
}
int main() {
Point p(10, 20);
cout << p << endl;
return 0;
}
Exception Handling
- An exception in C++ is an event that occurs during program execution that disrupts the normal flow of instructions. Common examples include division by zero, accessing invalid memory, or failing to open a file.
- Sample code
int x = -1;
// Some code
cout << "Before try \n";
try {
cout << "Inside try \n";
if (x < 0) {
// throwing an exception
throw x;
cout << "After throw (Never executed) \n";
}
}
catch (int x) {
cout << "Exception Caught \n";
}
- Catch any type of exceptions -
catch(...)
- Custom exception handling
class MyException : public std::exception {
public:
const char* what() const noexcept override {
return "My custom exception occurred!";
}
};
int main() {
try {
throw MyException();
} catch (const MyException& e) {
std::cout << e.what() << std::endl; // Handle custom exception
}
return 0;
}
Generics
- Generic Functions using Template
template <typename T>
T myMax(T x, T y)
{
return (x > y) ? x : y;
}
// Calling the generic function
myMax<int>(3, 7)
myMax<char>('g','e')
- Generics Class using Template
template <typename T>
class Array {
private:
T* ptr;
int size;
public:
Array(T arr[], int s);
void print();
};
- Generics with Multiple Types
template <class T, class U>
class A {
T x;
U y;
public:
A()
{
cout << "Constructor Called" << endl;
}
};
Lambda
- C++ 11 introduced lambda expressions to allow inline functions which can be used for short snippets of code that are not going to be reused and therefore do not require a name.
- Simplest lambda looks like this =
[capture clause](parameters) -> return_type { function body }
- For example a comparator function -
// Sort by increasing order
sort(vect.begin(), vect.end(), [](int a, int b){
return a < b;
})
- A lambda with an empty capture clause [ ] can only access variables which are local to it.
- A lambda expression can access variables from the enclosing scope. We can capture external variables from the enclosing scope in three ways :
- Capture by reference
- Capture by value
- Capture by both (mixed capture)
- Syntax used for capturing variables :
[&]
: capture all external variables by reference[=]
: capture all external variables by value[a, &b]
: capture a by value and b by reference
Multi Threading
- Launching a thread using Function Pointer
void functionName(param)
{
Statements;
}
// The parameters to the function are put after the comma
std::thread workerName(functionName, params);
Functors
- Functors in C++ are objects that can be called like functions by overloading the function call operator
operator()
- Types of Functors
- Generator Functors
Generator functors are used to generate a sequence of values when called repeatedly. They maintain internal state between calls to the
operator()
function to produce the next value in the sequence. An example is a Fibonacci number generator functor. - Unary Functors
Unary functors take a single argument of a specific type and return a value of another type. They are useful for transforming data or applying functions to sequences of values. An example is a
Square
functor that computes the square of a number. - Arithmetic Functors
C++ provides several predefined arithmetic functors in the
<functional>
header, such asplus
,minus
,multiplies
,divides
,modulus
, andnegate
. These perform basic arithmetic operations on two operands. - Relational Functors
Predefined relational functors in C++ include
equal_to
,not_equal_to
,greater
,greater_equal
,less
, andless_equal
. These compare two operands and return a boolean result. - Logical Functors
Logical functors like
logical_and
,logical_or
, andlogical_not
perform logical operations on boolean values. - Bitwise Functors
Bitwise functors such as
bit_and
,bit_or
, andbit_xor
perform bitwise operations on integral operands. In summary, functors in C++ provide a flexible and efficient way to encapsulate and reuse function-like behavior, with a wide range of applications from data transformation to algorithm implementation.
- Generator Functors
Generator functors are used to generate a sequence of values when called repeatedly. They maintain internal state between calls to the
OOPS
- Check this page to get all details of OOPS in c++[[OOPS]]
- Types of constructor
- Default constructor
- Parameterized constructor
- Copy constructor - a special constructor used to create a new object as a copy of an existing object.
class Person {
private:
string name;
int age;
public:
// Default constructor
Person(string n, int a) {
name = n;
age = a;
}
// Copy constructor
Person(const Person &p) {
name = p.name;
age = p.age;
cout << "Copy constructor called!" << endl;
}
void display() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
Person person1("Alice", 30); // Normal constructor
Person person2 = person1; // Copy constructor is called
person1.display();
person2.display();
}
- Move constructor
- A virtual function is a member function in a base class that you expect to be overridden in derived classes. It’s declared using the
virtual
keyword in the base class. - A friend class is a class that is given access to the private and protected members of another class. This is useful when two or more classes are closely related and need to interact with each other’s internals. For example LinkedList class can access the internals of the LinkedListNode class.
Snippets
// To split a string into vector array by a character
vector<string> split(string str, char delim){
vector<string> output;
int len = str.size();
int start = 0;
int end = str.find(delim);
while(end != -1){
output.push_back(str.substr(start, end - start));
start = end + 1;
end = str.find(delim, start);
}
output.push_back(str.substr(start));
return output;
}
Interesting Questions
- Difference between
long
andlong long
The C++ standard does not strictly define the size of long, leading to variability across different compilers and platforms. For instance, Microsoft’s compiler typically treats long as a 32-bit integer, while GCC may treat it as either a 32-bit or 64-bit integer depending on the architecture. Therefore, if you need guaranteed 64-bit integers, it’s advisable to use long long. - What is the difference between struct and class in C++? In C++, a class defined with the class keyword has private members and base classes by default. A structure is a class defined with the struct keyword. Its members and base classes are public by default. In practice, structs are typically reserved for data without functions.