C++ Constructors & Destructors Quiz

C++
0 Passed
0% acceptance

40 in-depth questions covering C++ constructors and destructors, including default/parameterized constructors, initializer lists, copy/move constructors, and RAII concepts — with 16 code examples to master object lifecycle management.

40 Questions
~80 minutes
1

Question 1

What is the primary purpose of a constructor in C++?

A
To initialize an object's data members and establish its initial state when the object is created
B
To destroy objects when they go out of scope
C
To copy objects from one location to another
D
To compare two objects for equality
2

Question 2

What is the key difference between a default constructor and a parameterized constructor?

A
Default constructors take no parameters and provide basic initialization, while parameterized constructors accept arguments to customize object initialization with specific values
B
Default constructors are automatically generated, parameterized constructors must be explicitly defined
C
Default constructors initialize to zero, parameterized constructors initialize to provided values
D
There is no functional difference between them
3

Question 3

When is a destructor called in C++?

A
When an object goes out of scope or is explicitly deleted, allowing cleanup of resources like memory, file handles, or network connections
B
When an object is created
C
When an object is copied
D
When an object is moved
4

Question 4

What is the main advantage of using initializer lists over assignment in constructors?

A
Initializer lists directly construct members with provided values, avoiding default construction followed by assignment, which is more efficient and required for const/reference members
B
Initializer lists are slower but more readable
C
Assignment in constructor body provides better performance
D
Initializer lists cannot be used with primitive types
5

Question 5

What is a copy constructor and when is it called?

cpp
#include <iostream>
#include <string>

class Person {
private:
    std::string name;
    int age;
public:
    Person(const std::string& n, int a) : name(n), age(a) {
        std::cout << "Constructor called for " << name << std::endl;
    }
    
    Person(const Person& other) : name(other.name), age(other.age) {
        std::cout << "Copy constructor called for " << name << std::endl;
    }
};

int main() {
    Person p1("Alice", 30);
    Person p2 = p1;  // Copy constructor called
    
    return 0;
}
A
A copy constructor creates a new object as a copy of an existing object and is called during pass-by-value, return by value, and explicit copying operations
B
A copy constructor moves resources from one object to another
C
A copy constructor is called when objects are destroyed
D
A copy constructor initializes objects with default values
6

Question 6

What is the Rule of Three in C++?

A
If a class defines any of copy constructor, copy assignment operator, or destructor, it should probably define all three to manage resources correctly
B
A class should have exactly three constructors
C
Objects should be initialized in three different ways
D
Destructors should be called three times for each object
7

Question 7

What is RAII and why is it important?

A
Resource Acquisition Is Initialization ties resource management to object lifetime, ensuring automatic cleanup through destructors and providing exception-safe resource handling
B
RAII is a way to initialize arrays automatically
C
RAII stands for Random Access Integer Initialization
D
RAII is used for runtime type identification
8

Question 8

What is a move constructor and how does it differ from a copy constructor?

cpp
#include <iostream>
#include <string>
#include <vector>

class Resource {
private:
    std::vector<int> data;
public:
    Resource(size_t size) : data(size, 42) {
        std::cout << "Resource created with " << size << " elements" << std::endl;
    }
    
    // Copy constructor - expensive
    Resource(const Resource& other) : data(other.data) {
        std::cout << "Copy constructor called" << std::endl;
    }
    
    // Move constructor - efficient
    Resource(Resource&& other) noexcept : data(std::move(other.data)) {
        std::cout << "Move constructor called" << std::endl;
    }
};

Resource createResource() {
    return Resource(1000);
}

int main() {
    Resource res = createResource();  // Move constructor called
    
    return 0;
}
A
Move constructor transfers ownership of resources from a temporary object using rvalue references, avoiding expensive copies while leaving the source in a valid but unspecified state
B
Move constructor creates a duplicate of an object
C
Move constructor is called for lvalue objects only
D
Move constructor and copy constructor are identical
9

Question 9

What happens if you don't provide a default constructor for a class?

A
The compiler may generate one if no constructors are defined, but if any constructor is provided, no default constructor is generated automatically
B
The compiler always generates a default constructor
C
The class cannot be instantiated
D
All objects will be initialized to null
10

Question 10

What is the purpose of the noexcept specifier on move constructors?

A
Noexcept on move constructors allows the compiler to optimize operations like std::vector resize, ensuring move constructors are used instead of copy constructors for efficiency
B
Noexcept prevents exceptions from being thrown in move constructors
C
Noexcept makes move constructors faster
D
Noexcept is required for all move constructors
11

Question 11

What is constructor initialization order and why does it matter?

cpp
#include <iostream>

class A {
public:
    A() { std::cout << "A constructed" << std::endl; }
};

class B {
public:
    B() { std::cout << "B constructed" << std::endl; }
};

class Test {
private:
    A a;
    B b;
public:
    Test() : b(), a() {  // Initialization order is a, then b
        std::cout << "Test constructed" << std::endl;
    }
};

int main() {
    Test t;
    return 0;
}
A
Members are initialized in declaration order within the class, regardless of the order in the initializer list, which can lead to unexpected behavior if initialization depends on other members
B
Members are initialized in the order they appear in the initializer list
C
Members are initialized in alphabetical order
D
Initialization order doesn't affect program behavior
12

Question 12

What is the difference between delete and delete[] for destructors?

A
Delete calls destructor once for single objects, while delete[] calls destructor for each element in an array and handles proper cleanup of array allocations
B
Delete[] is used for single objects, delete for arrays
C
They are completely interchangeable
D
Delete[] doesn't call destructors
13

Question 13

What is a conversion constructor and when is it useful?

cpp
#include <iostream>
#include <string>

class StringWrapper {
private:
    std::string data;
public:
    StringWrapper(const std::string& s) : data(s) {}  // Conversion constructor
    
    void print() const {
        std::cout << data << std::endl;
    }
};

void processWrapper(StringWrapper sw) {
    sw.print();
}

int main() {
    std::string str = "Hello";
    processWrapper(str);  // Implicit conversion
    
    return 0;
}
A
A constructor that takes a single argument of a different type enables implicit conversions, allowing objects to be created from compatible types for convenient interfaces
B
A constructor that converts objects to primitive types
C
A constructor that prevents implicit conversions
D
A constructor used only for copying objects
14

Question 14

What is copy elision and why is it beneficial?

A
Copy elision is a compiler optimization that eliminates unnecessary copy operations, directly constructing objects in their final destination to improve performance
B
Copy elision prevents objects from being copied
C
Copy elision forces additional copies for safety
D
Copy elision is a deprecated feature
15

Question 15

What is the Rule of Zero in modern C++?

A
Classes that manage resources should define none of the special member functions, instead using smart pointers and standard library types that handle resource management automatically
B
Classes should define all special member functions as defaulted
C
Classes should never define constructors
D
Classes should define exactly zero member functions
16

Question 16

What happens when a constructor throws an exception?

cpp
#include <iostream>
#include <stdexcept>

class Resource {
private:
    int* data;
public:
    Resource(int value) {
        if(value < 0) {
            throw std::invalid_argument("Negative value not allowed");
        }
        data = new int(value);
        std::cout << "Resource created" << std::endl;
    }
    
    ~Resource() {
        delete data;
        std::cout << "Resource destroyed" << std::endl;
    }
};

int main() {
    try {
        Resource r(-1);  // Exception thrown
    } catch(const std::exception& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }
    
    return 0;
}
A
If a constructor throws an exception, the object is not fully constructed, destructors are called for successfully constructed members, and the object is not usable
B
The constructor completes normally and the object is created
C
The exception is silently ignored
D
The program terminates immediately
17

Question 17

What is the difference between std::move and copying in terms of object state?

A
Move operations transfer ownership and leave the source object in a valid but unspecified state, while copy operations create independent duplicates that leave the source unchanged
B
Move operations destroy the source object
C
Copy operations are always more efficient than move operations
D
Move and copy operations have identical effects
18

Question 18

What is the purpose of explicit constructors?

cpp
#include <iostream>

class Integer {
private:
    int value;
public:
    explicit Integer(int v) : value(v) {}  // Prevents implicit conversion
    
    void print() const {
        std::cout << value << std::endl;
    }
};

void processInteger(Integer i) {
    i.print();
}

int main() {
    // processInteger(42);  // ERROR: explicit constructor
    processInteger(Integer(42));  // OK: explicit conversion
    
    return 0;
}
A
Explicit prevents implicit conversions from the constructor's parameter type to the class type, avoiding unintended conversions that could lead to bugs
B
Explicit makes constructors faster
C
Explicit is required for all constructors
D
Explicit allows implicit conversions
19

Question 19

What is the relationship between constructors and virtual functions?

A
Constructors cannot be virtual because virtual functions rely on the vtable which isn't set up until after the base constructor completes, preventing polymorphic construction
B
Constructors can be virtual and are commonly used
C
Virtual constructors are used for copying objects
D
All constructors are virtual by default
20

Question 20

What is the most important consideration when implementing RAII for file handling?

cpp
#include <iostream>
#include <fstream>
#include <string>

class FileHandler {
private:
    std::ifstream file;
public:
    FileHandler(const std::string& filename) {
        file.open(filename);
        if(!file.is_open()) {
            throw std::runtime_error("Failed to open file");
        }
    }
    
    ~FileHandler() {
        if(file.is_open()) {
            file.close();
        }
    }
    
    std::string readLine() {
        std::string line;
        std::getline(file, line);
        return line;
    }
    
    bool isOpen() const {
        return file.is_open();
    }
};

int main() {
    try {
        FileHandler handler("data.txt");
        if(handler.isOpen()) {
            std::cout << handler.readLine() << std::endl;
        }
    } catch(const std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
    }
    // File automatically closed here
    
    return 0;
}
A
RAII ensures file handles are automatically closed when the object goes out of scope, preventing resource leaks even if exceptions occur during processing
B
RAII requires manual resource cleanup
C
RAII is not suitable for file handling
D
RAII makes file operations slower
21

Question 21

What is the key benefit of move constructors over copy constructors for expensive resources?

A
Move constructors transfer ownership of resources instead of duplicating them, providing O(1) operations instead of O(n) copies for large objects like vectors or strings
B
Move constructors are always slower than copy constructors
C
Move constructors create exact duplicates
D
Move constructors cannot be used with standard library types
22

Question 22

What happens to member initialization order when using inheritance?

A
Base class constructors run first in inheritance order, then derived class members are initialized in declaration order, ensuring proper construction hierarchy
B
Derived class members are initialized before base class
C
Initialization order is random and unpredictable
D
Inheritance doesn't affect initialization order
23

Question 23

What is the difference between = default and providing an empty constructor body?

cpp
#include <iostream>

class A {
public:
    A() = default;  // Compiler generates default initialization
};

class B {
public:
    B() {}  // User-defined, does nothing
};

class C {
private:
    int x;
public:
    C() = default;  // x gets default initialization (0)
};

class D {
private:
    int x;
public:
    D() {}  // x is uninitialized!
};

int main() {
    D d;
    // d.x is uninitialized - undefined behavior!
    
    return 0;
}
A
= default explicitly requests compiler-generated default initialization for all members, while empty constructor body leaves members uninitialized if they have no default constructors
B
They are completely identical in behavior
C
= default is deprecated in modern C++
D
Empty constructor body provides better performance
24

Question 24

What is the most common pitfall when implementing copy constructors?

A
Shallow copying pointer members instead of deep copying, leading to shared ownership and double deletion when objects are destroyed
B
Copy constructors cannot access private members
C
Copy constructors are always generated by the compiler
D
Copy constructors should never be implemented
25

Question 25

What is the relationship between smart pointers and RAII?

A
Smart pointers implement RAII by automatically managing resource lifetime through their destructors, eliminating manual memory management and preventing leaks
B
Smart pointers replace RAII entirely
C
RAII is only used with raw pointers
D
Smart pointers make RAII unnecessary
26

Question 26

What is the Rule of Five in C++11 and later?

A
If a class defines any of destructor, copy constructor, copy assignment, move constructor, or move assignment, it should define all five for complete resource management
B
A class should have exactly five constructors
C
The Rule of Three plus move operations
D
Classes should define five different destructors
27

Question 27

What is the most important reason to use initializer lists for const members?

cpp
#include <iostream>

class ConstExample {
private:
    const int value;
public:
    // ConstExample(int v) { value = v; }  // ERROR: cannot assign to const
    ConstExample(int v) : value(v) {}     // OK: initialize const member
    
    void print() const {
        std::cout << value << std::endl;
    }
};

int main() {
    ConstExample ex(42);
    ex.print();
    
    return 0;
}
A
Const members must be initialized in the initializer list because they cannot be assigned to after declaration, and constructor body assignment is too late
B
Const members can be assigned in the constructor body
C
Initializer lists are optional for const members
D
Const members don't need initialization
28

Question 28

What is the difference between lvalues and rvalues in the context of move constructors?

A
Lvalues have names and persist beyond a single expression, while rvalues are temporary objects that can be safely moved from since they won't be used again
B
Lvalues are always on the left side of assignments, rvalues on the right
C
Lvalues can be moved, rvalues cannot
D
There is no difference in modern C++
29

Question 29

What happens when a destructor is declared as virtual?

cpp
#include <iostream>

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

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

int main() {
    Base* ptr = new Derived();
    delete ptr;  // Calls both destructors
    
    return 0;
}
A
Virtual destructors ensure the correct destructor is called for derived objects when deleted through base class pointers, preventing resource leaks in inheritance hierarchies
B
Virtual destructors make destruction slower
C
Virtual destructors prevent inheritance
D
All destructors are virtual by default
30

Question 30

What is the most efficient way to initialize a member that is itself a class with a constructor?

A
Use initializer list to directly construct the member with its constructor parameters, avoiding default construction followed by assignment
B
Always assign in the constructor body for clarity
C
Use default construction then call setter methods
D
Member initialization efficiency doesn't matter
31

Question 31

What is the key difference between std::unique_ptr and raw pointers in RAII?

A
Unique_ptr automatically manages the lifetime of the pointed-to object through its destructor, eliminating manual delete calls and preventing memory leaks
B
Unique_ptr allows multiple owners of the same resource
C
Raw pointers provide automatic memory management
D
Unique_ptr cannot be used in RAII patterns
32

Question 32

What is the most common mistake when implementing move constructors?

cpp
#include <iostream>
#include <vector>

class BadMove {
private:
    std::vector<int> data;
public:
    BadMove(size_t size) : data(size, 42) {}
    
    // Bad move constructor - leaves source in invalid state
    BadMove(BadMove&& other) {
        data = std::move(other.data);  // Assignment, not initialization
        // other.data is now empty, but object is still valid
    }
};

class GoodMove {
private:
    std::vector<int> data;
public:
    GoodMove(size_t size) : data(size, 42) {}
    
    // Good move constructor - uses initializer list
    GoodMove(GoodMove&& other) noexcept : data(std::move(other.data)) {}
};

int main() {
    BadMove b1(100);
    BadMove b2 = std::move(b1);  // Less efficient due to assignment
    
    GoodMove g1(100);
    GoodMove g2 = std::move(g1);  // More efficient
    
    return 0;
}
A
Using assignment instead of initializer list in move constructors, which causes unnecessary default construction of members before moving into them
B
Forgetting to mark move constructors as noexcept
C
Move constructors should never be implemented
D
Using copy instead of move operations
33

Question 33

What is the relationship between exceptions and RAII?

A
RAII ensures resources are properly cleaned up even when exceptions occur, because destructors are called during stack unwinding, providing exception safety
B
RAII prevents exceptions from being thrown
C
Exceptions break RAII patterns
D
RAII is only useful in code without exceptions
34

Question 34

What is the most important consideration when choosing between copy and move for a class member?

A
Use move operations for members that own resources to transfer ownership efficiently, while copy operations create independent duplicates for shared or immutable data
B
Always use copy operations for safety
C
Always use move operations for performance
D
The choice doesn't affect performance
35

Question 35

What happens when you don't declare a destructor but use smart pointers?

A
Smart pointers handle resource cleanup automatically through their own destructors, so explicit destructors are often unnecessary when using RAII types
B
Smart pointers require explicit destructors
C
Smart pointers don't work without destructors
D
Destructors become more important with smart pointers
36

Question 36

What is the key benefit of using delegating constructors?

cpp
#include <iostream>

class Point {
private:
    double x, y;
public:
    Point(double x_val, double y_val) : x(x_val), y(y_val) {
        std::cout << "Point constructed" << std::endl;
    }
    
    Point() : Point(0.0, 0.0) {}  // Delegate to main constructor
    
    Point(double x_val) : Point(x_val, 0.0) {}  // Delegate with default y
};

int main() {
    Point p1;      // (0, 0)
    Point p2(5.0); // (5, 0)
    Point p3(1, 2); // (1, 2)
    
    return 0;
}
A
Delegating constructors reduce code duplication by having simpler constructors call the main constructor, ensuring consistent initialization logic in one place
B
Delegating constructors make object creation slower
C
Delegating constructors cannot be used with initializer lists
D
All constructors must be delegating
37

Question 37

What is the most important rule for implementing destructors in inheritance hierarchies?

A
Base class destructors should be virtual to ensure derived class destructors are called when deleting through base class pointers, preventing undefined behavior and resource leaks
B
Destructors should never be virtual
C
Only derived classes need destructors
D
Virtual destructors are automatically generated
38

Question 38

What is the difference between std::move and std::forward?

A
std::move unconditionally casts to rvalue reference for moving, while std::forward preserves value category for perfect forwarding in template functions
B
std::forward is used for copying, std::move for moving
C
They are identical and interchangeable
D
std::move is for lvalues, std::forward for rvalues
39

Question 39

What is the most common performance issue with copy constructors?

A
Expensive deep copying of large data structures like vectors or strings, especially when the copy is immediately discarded or not needed
B
Copy constructors are always optimized by compilers
C
Copy constructors cannot be made efficient
D
Copy constructors don't affect performance
40

Question 40

What is the fundamental principle that guides when to implement custom constructors and destructors?

A
Implement custom special member functions only when a class manages resources that require non-trivial initialization, copying, moving, or cleanup beyond what compiler-generated versions provide
B
All classes should have custom constructors and destructors
C
Custom constructors and destructors should never be implemented
D
The choice doesn't affect class behavior

QUIZZES IN C++