Author: tech.ctoi.in

  • Understanding Smart Pointers in C++

    Smart pointers are an essential feature in C++. They manage memory automatically, preventing leaks. The main types are `unique_ptr`, `shared_ptr`, and `weak_ptr`. Using smart pointers improves code safety and readability. Here’s a simple example of `unique_ptr`:

    “`cpp
    #include
    #include
    using namespace std;
    int main() {
    unique_ptr ptr(new int(10));
    cout << *ptr << endl; // Outputs 10 return 0; } ``` In this example, `unique_ptr` takes ownership of the integer. It automatically deallocates memory when it goes out of scope. Smart pointers reduce manual memory management issues.

  • Understanding RAII in C++

    RAII stands for Resource Acquisition Is Initialization. It ties resource management to object lifetime. When an object is created, resources are acquired. When it goes out of scope, resources are released. Here’s an example:

    “`cpp
    #include
    #include
    using namespace std;
    class Resource {
    public:
    Resource() { cout << "Resource acquired" << endl; } ~Resource() { cout << "Resource released" << endl; } }; int main() { Resource res; // Acquired return 0; } ``` In this code, the resource is automatically released. RAII helps prevent memory leaks and simplifies management.

  • Understanding Templates in C++

    Templates allow you to write generic and reusable code. You can create functions or classes that work with any type. Templates enhance flexibility and reduce redundancy. Here’s an example of a simple template function:

    “`cpp
    #include
    using namespace std;
    template
    T add(T a, T b) { return a + b; }
    int main() {
    cout << add(5, 10) << endl; // Outputs 15 return 0; } ``` In this example, the `add` function works with any type. Templates promote code reuse and type safety.

  • Introduction to C++ Standard Template Library (STL)

    The C++ Standard Template Library (STL) provides useful components. It includes algorithms, containers, and iterators. STL enhances productivity and code quality. Common containers are `vector`, `list`, and `map`. Here’s an example using `vector`:

    “`cpp
    #include
    #include
    using namespace std;
    int main() {
    vector nums = {1, 2, 3};
    nums.push_back(4);
    for (int n : nums) cout << n << " "; // Outputs 1 2 3 4 return 0; } ``` In this example, `vector` provides dynamic array functionality. STL simplifies complex programming tasks.

  • Using std::visit with Variant Types in C++17

    C++17 introduced `std::variant` for type-safe unions. You can hold multiple types in a single variable. `std::visit` allows you to apply a function to the active type. This simplifies working with variants. Here’s an example:

    “`cpp
    #include
    #include
    using namespace std;
    void visitor(int i) { cout << "Integer: " << i << endl; } void visitor(const string& s) { cout << "String: " << s << endl; } int main() { variant var = “Hello”;
    visit(visitor, var); // Outputs String: Hello
    return 0;
    }
    “`

    In this code, `std::visit` calls the appropriate visitor function. This approach enhances code clarity and safety.

  • Implementing Type Erasure in C++

    Type erasure allows you to hide type information. This promotes flexibility and code reuse in C++. You can achieve type erasure with interfaces and inheritance. Here’s a simple example:

    
    #include 
    #include 
    using namespace std;
    class Base {
    public:
         virtual void draw() = 0;
    };
    class Circle : public Base {
    public:
          void draw() override { cout << "Circle" << endl; } }; int main() { unique_ptr shape = make_unique();
              shape->draw(); // Outputs Circle
              return 0;
          }
    }
    In this example, `Base` is an interface for different shapes. Type erasure allows dynamic type handling.
  • Using std::chrono for Time-Related Operations in C++

    The `std::chrono` library provides tools for time management. You can measure time intervals and durations easily. This library enhances precision in time-related tasks. Here’s an example:

    “`cpp
    #include
    #include
    using namespace std;
    using namespace std::chrono;
    int main() {
    auto start = high_resolution_clock::now();
    // Simulate work with a sleep function
    this_thread::sleep_for(milliseconds(100));
    auto end = high_resolution_clock::now();
    auto duration = duration_cast(end – start);
    cout << "Duration: " << duration.count() << " ms" << endl; return 0; } ``` In this code, `std::chrono` measures the time taken for execution. It simplifies timing operations significantly.

  • Using std::bind and std::function in C++

    `std::bind` and `std::function` enhance function flexibility. `std::function` can store any callable object. `std::bind` allows you to bind arguments to functions. Here’s an example:

    
    ```#include 
    #include 
    using namespace std;
    void greet(string name) { 
           cout << "Hello, " << name << endl; 
    } 
    int main() { 
        auto boundGreet = bind(greet, "Alice"); 
         boundGreet(); // Outputs Hello, Alice return 0; 
    } ``` 
    
    In this code, `std::bind` simplifies function calls with parameters. These tools improve code clarity and maintainability.
  • Understanding std::optional in C++

    `std::optional` represents an optional value. It indicates whether a value is present or not. This helps avoid null pointer exceptions. Here’s a simple example:

    ```cpp
    #include 
    #include
    using namespace std;
    optional getValue(bool provide) {
        if (provide) return 42;
        return nullopt;
    }
    int main() {
        auto val = getValue(true);
        if (val) cout << *val << endl; // Outputs 42 
    return 0; 
    } ```

    In this code, `std::optional` safely handles potential absence of values. It makes code cleaner and more reliable.

  • How do you implement polymorphism in C++?

    Polymorphism in C++ allows objects of different types to be treated uniformly. It comes in two forms: compile-time (or static) polymorphism and runtime (or dynamic) polymorphism.

    Compile-time polymorphism is achieved through function overloading and operator overloading. Function overloading lets multiple functions with the same name behave differently based on their parameters.

    Runtime polymorphism is implemented using inheritance and virtual functions. It allows derived class methods to override base class methods and enables the object to call the appropriate method at runtime.

    Using polymorphism makes the code more flexible and scalable. You can define common interfaces in base classes, and the derived classes implement their specific behavior.

    
    // Example of polymorphism in C++
    #include 
    using namespace std;
    
    class Shape {
        public:
            virtual void draw() {
                cout << "Drawing a shape" << endl;
            }
    };
    
    class Circle : public Shape {
        public:
            void draw() override {
                cout << "Drawing a circle" << endl;
            }
    };
    
    class Rectangle : public Shape {
        public:
            void draw() override {
                cout << "Drawing a rectangle" << endl;
            }
    };
    
    int main() {
        Shape* shape1 = new Circle();
        Shape* shape2 = new Rectangle();
        shape1->draw();  // Drawing a circle
        shape2->draw();  // Drawing a rectangle
        delete shape1;
        delete shape2;
        return 0;
    }