Q6: What is the difference between stack memory and heap memory in C++?
Stack Memory:
Heap Memory:
delete
or
free
.
Q7: Explain the concept of "this" pointer in C++.
The
this
pointer is an implicit pointer available in non-static member functions of a class. It points to the object for which the member function is called. It is used to access members of the object within the member functions and to distinguish between member variables and parameters with the same name.
Example:
class MyClass {
int value;
public:
void setValue(int value) {
this->value = value; // 'this->value' refers to the member variable, 'value' refers to the parameter
}
};
Q8: What are friend functions and friend classes in C++?
Friend Function:
A friend function is a function that is not a member of a class but has access to its private and protected members. It is declared using the
friend
keyword inside the class.
Friend Class: A friend class is a class that can access the private and protected members of another class in which it is declared as a friend.
Example of friend function:
class MyClass {
private:
int secret;
public:
MyClass(int s) : secret(s) {}
friend void revealSecret(const MyClass& obj);
};
void revealSecret(const MyClass& obj) {
std::cout << obj.secret << std::endl;
}
Q9: What is function overloading and how is it different from function overriding?
Function Overloading:
Function Overriding:
Example of overloading:
class Example {
public:
void func(int x) {}
void func(double x) {}
void func(int x, double y) {}
};
Q10: Explain the difference between const member functions and non-const member functions.
Const Member Functions:
const
keyword at the end of the function signature.
Non-const Member Functions:
Example:
class MyClass {
int value;
public:
int getValue() const { return value; } // Const member function
void setValue(int v) { value = v; } // Non-const member function
};
Request question
Please fill in the form below to submit your question.
Q11: What is the significance of the explicit keyword in C++?
The
explicit
keyword is used to prevent the compiler from using constructors for implicit type conversions. It is applied to constructors that can be called with a single argument. This ensures that such constructors can only be used for direct initialization and not for implicit conversions.
class MyClass {
public:
explicit MyClass(int x) {}
};
MyClass obj1 = 10; // Error: implicit conversion not allowed
MyClass obj2(10); // Ok: direct initialization
Q12: Explain the concept of move semantics and the use of std::move in C++.
Move semantics allow the resources of a temporary object to be moved to another object, rather than copied. This is particularly useful for optimizing the performance of code by eliminating unnecessary copies. The
std::move
function is used to indicate that an object’s resources can be moved.
class MyClass {
std::string data;
public:
MyClass(std::string d) : data(std::move(d)) {}
};
Q13: What is the difference between std::vector and std::array?
std::vector:
push_back
,
pop_back
).
std::array:
Example:
std::vector vec = {1, 2, 3};
std::array arr = {1, 2, 3};
Q14: What is the Rule of Three in C++?
The Rule of Three states that if a class defines one (or more) of the following, it should probably explicitly define all three:
This is because these functions are often closely related, and failing to properly define one might lead to resource management issues.
class MyClass {
int* data;
public:
MyClass() : data(new int[10]) {}
~MyClass() { delete[] data; }
MyClass(const MyClass& other) {
data = new int[10];
std::copy(other.data, other.data + 10, data);
}
MyClass& operator=(const MyClass& other) {
if (this != &other) {
delete[] data;
data = new int[10];
std::copy(other.data, other.data + 10, data);
}
return *this;
}
};
Q15: What are smart pointers in C++ and why are they used?
Smart pointers are objects that manage the lifetime of dynamically allocated objects. They are used to ensure that resources are properly released when they are no longer needed, preventing memory leaks and dangling pointers. C++ provides several types of smart pointers:
std::unique_ptr
: Manages a unique resource, ensuring that there is only one owner.
std::shared_ptr
: Manages a resource with shared ownership, using reference counting.
std::weak_ptr
: A weak reference to a
std::shared_ptr
that does not affect the reference count.
Example of
std::unique_ptr
:
std::unique_ptr ptr = std::make_unique(10);
Request question
Please fill in the form below to submit your question.
Q16: What is the difference between struct and class in C++?
struct:
class:
Both
struct
and
class
can have member functions, constructors, destructors, and can participate in inheritance.
Example:
struct MyStruct {
int data;
void func() {}
};
class MyClass {
private:
int data;
public:
void func() {}
};
Q17: What is an inline function and when would you use it?
An inline function is a function where the compiler attempts to expand the function's body at each call site, instead of performing a regular function call. This can improve performance by eliminating the overhead of a function call, especially for small functions. However, it can increase the binary size.
Syntax:
inline void func() {
// Function body
}
Usage:
Q18: Explain what a lambda function is in C++ and provide an example.
A lambda function is an anonymous function defined within a scope and can capture variables from its enclosing scope. It is used for short, inline functions that are not reusable elsewhere.
Syntax:
[ capture list ] ( parameters ) -> return type {
// Function body
}
Example:
auto add = [](int a, int b) -> int {
return a + b;
};
std::cout << add(2, 3); // Outputs: 5
Q19: What is the purpose of the mutable keyword in C++?
The
mutable
keyword is used to allow a member of an object to be modified even if the object is declared as
const
. This is useful for members that are conceptually not part of the object's logical state but need to be modified, such as caching mechanisms.
class MyClass {
mutable int cache;
public:
int getCache() const {
cache++; // Allowed because cache is mutable
return cache;
}
};
Q20: What is the purpose of namespaces in C++?
Namespaces are used to organize code into logical groups and to prevent name collisions in larger projects. They allow for the same names to be used in different contexts without conflict.
Example:
namespace MyNamespace {
void func() {
std::cout << "Inside MyNamespace" << std::endl;
}
}
int main() {
MyNamespace::func();
return 0;
}
Request question
Please fill in the form below to submit your question.
Request question
Please fill in the form below to submit your question.
Request question
Please fill in the form below to submit your question.
(Basic)
#include
int main() {
int arr[] = {1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i <= 5; i++) {
sum += arr[i];
}
std::cout << "Sum: " << sum << std::endl;
return 0;
}
Answer: The error is in the loop condition
i <= 5
. It should be
i < 5
because array indices start from 0 and go up to 4 for an array of size 5.
Corrected Code:
#include
int main() {
int arr[] = {1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += arr[i];
}
std::cout << "Sum: " << sum << std::endl;
return 0;
}
(Basic)
#include
int factorial(int n) {
if (n == 0) return 1;
return n * factorial(n - 1);
}
int main() {
int num = 5;
std::cout << "Factorial of " << num << " is " << factorial(num) << std::endl;
return 0;
}
(Intermediate)
#include
int sumOfNaturals(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
int main() {
int num = 100;
std::cout << "Sum of first " << num << " natural numbers is " << sumOfNaturals(num) << std::endl;
return 0;
}
The optimized version uses the formula for the sum of the first n natural numbers:
n * (n + 1) / 2
.
Optimized Code:
#include
int sumOfNaturals(int n) {
return n * (n + 1) / 2;
}
int main() {
int num = 100;
std::cout << "Sum of first " << num << " natural numbers is " << sumOfNaturals(num) << std::endl;
return 0;
}
(Intermediate)
#include
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 5, y = 10;
swap(x, y);
std::cout << "x: " << x << ", y: " << y << std::endl;
return 0;
}
The output will be:
x: 10, y: 5
This is because the
swap
function correctly swaps the values of
x
and
y
using references.
(Intermediate)
#include
bool isPrime(int num) {
if (num <= 1) return false;
for (int i = 2; i <= num / 2; i++) {
if (num % i == 0) return false;
}
return true;
}
int main() {
int num = 29;
if (isPrime(num)) {
std::cout << num << " is a prime number." << std::endl;
} else {
std::cout << num << " is not a prime number." << std::endl;
}
return 0;
}
(Intermediate)
#include
int stringLength(const char* str) {
int length = 0;
while (str[length] != '\0') {
length++;
}
return length;
}
int main() {
const char* text = "Hello, World!";
std::cout << "Length: " << stringLength(text) << std::endl;
return 0;
}
There is no error in the provided code. It correctly calculates the length of the string. However, if the problem intended to test for potential pitfalls, ensure that
str
is not null before proceeding.
Improved Code with Null Check:
#include
int stringLength(const char* str) {
if (str == nullptr) return 0;
int length = 0;
while (str[length] != '\0') {
length++;
}
return length;
}
int main() {
const char* text = "Hello, World!";
std::cout << "Length: " << stringLength(text) << std::endl;
return 0;
}
(Advanced)
#include
int findMax(int arr[], int size) {
int max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
int main() {
int arr[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
int size = sizeof(arr) / sizeof(arr[0]);
std::cout << "Max element is " << findMax(arr, size) << std::endl;
return 0;
}
Improved Code using
std::max_element
:
#include
#include
int findMax(const int arr[], int size) {
return *std::max_element(arr, arr + size);
}
int main() {
int arr[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
int size = sizeof(arr) / sizeof(arr[0]);
std::cout << "Max element is " << findMax(arr, size) << std::endl;
return 0;
}
(Advanced)
#include
#include
int maxSubArraySum(std::vector& arr) {
int maxSum = arr[0];
for (size_t i = 0; i < arr.size(); i++) {
int currentSum = 0;
for (size_t j = i; j < arr.size(); j++) {
currentSum += arr[j];
if (currentSum > maxSum) {
maxSum = currentSum;
}
}
}
return maxSum;
}
int main() {
std::vector arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
std::cout << "Maximum subarray sum is " << maxSubArraySum(arr) << std::endl;
return 0;
}
The optimized version uses Kadane's Algorithm which has a time complexity of O(n).
Optimized Code:
#include
#include
int maxSubArraySum(std::vector& arr) {
int maxSum = arr[0];
int currentSum = arr[0];
for (size_t i = 1; i < arr.size(); i++) {
currentSum = std::max(arr[i], currentSum + arr[i]);
maxSum = std::max(maxSum, currentSum);
}
return maxSum;
}
int main() {
std::vector arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
std::cout << "Maximum subarray sum is " << maxSubArraySum(arr) << std::endl;
return 0;
}
(Advanced)
#include
class Base {
public:
virtual void show() {
std::cout << "Base class" << std::endl;
}
};
class Derived : public Base {
public:
void show() override {
std::cout << "Derived class" << std::endl;
}
};
int main() {
Base* b;
Derived d;
b = &d
b->show();
return 0;
}
The output will be:
Derived class
This is because
show
is a virtual function, and the pointer
b
points to an object of type
Derived
. Thus, the
show
method of the
Derived
class is called.
(Advanced)
#include
#include
std::vector mergeArrays(const std::vector& arr1, const std::vector& arr2) {
std::vector merged;
merged.reserve(arr1.size() + arr2.size());
size_t i = 0, j = 0;
while (i < arr1.size() && j < arr2.size()) {
if (arr1[i] < arr2[j]) {
merged.push_back(arr1[i++]);
} else {
merged.push_back(arr2[j++]);
}
}
while (i < arr1.size()) {
merged.push_back(arr1[i++]);
}
while (j < arr2.size()) {
merged.push_back(arr2[j++]);
}
return merged;
}
int main() {
std::vector arr1 = {1, 3, 5, 7};
std::vector arr2 = {2, 4, 6, 8};
std::vector merged = mergeArrays(arr1, arr2);
for (int num : merged) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
The given code is already efficient with a time complexity of O(n + m), where n and m are the sizes of the two arrays. However, using
reserve
before merging improves performance by avoiding multiple reallocations.
The original code is efficient, but if it needs further improvement or adjustments, it should focus on algorithmic optimizations or additional error handling based on specific requirements.
Overview of C++