Notes
C Plus Plus
C Plus Plus
  • Roadmap
    • 🛣️C Plus Plus: Docs
  • Build
    • 🔥Build Process
    • 🔧Connect multiple C++ Files
  • Code
    • ⏮️Pre-Processors
      • #include
      • #define
      • #ifdef
      • #pragma
      • Predefined Macros
    • LValue and RValue
    • 🪅Data Types
      • Enum
      • TypeDef
      • const in c++
      • extern vs inline
    • 🎭Casting
    • 🔃Operator overloading
      • Available Operators
      • Examples of operator overloading
    • 🗺️Namespace
      • Namespace Example
      • Using directive
    • 🕵️Header File
      • For C++ Classes
    • 🏗️Structure
      • Struct vs Class
      • Public vs Private inheritance
    • 🏢Classes
      • Friend Function
      • Copy Constructor
      • Explicit Constructor
      • Move Constructor
        • Move Semantics
      • Other constructors
      • Virtual functions
      • Pure virtual function
      • Other function declaration
      • const function vs final function
  • Memory
    • 🧠Memory Introduction
    • ✨Heap and Stack
    • 🎯Pointers
      • Dangling Pointer
      • 'this' Pointer
      • Function Pointer
      • Smart Pointers
        • Unique Pointer
        • Shared Pointer
        • Weak Pointer
      • Reference count
    • 👨‍🏭Helper function
    • 🍡Vector [ArrayList]
      • Custom vector, part 1
      • Custom vector, part 2
      • Custom vector, part 3
      • std::vector
    • ♻️Union
      • Type Punning
      • Type Punning, part 2
      • Type Punning, part 3
      • Union, part 1
      • Union, Part 2
  • Thread
    • 🧵Threading
      • std::thread
      • Detach a thread
  • Misc
    • 🗂️Execution Order
    • 🧠Print memory
Powered by GitBook
On this page
  1. Memory
  2. Vector [ArrayList]

std::vector

In Custom vector, part 3, we tried most of the things that we can do to optimize our vector, but still we end up using unnecessary memory. Thus, instead of trying to create a perfect implementation, we can use a std::vector implementation that will provide is the most optimised way to create a vector.

Here's a brief explanation along with an example:

#include <iostream>
#include <vector>
#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;
    }

    // Copy constructor
    Person(const Person& other) : name(other.name), age(other.age) {
        std::cout << "Copy constructor called for " << name << std::endl;
    }

    // Move constructor
    Person(Person&& other) noexcept : name(std::move(other.name)), age(other.age) {
        std::cout << "Move constructor called for " << name << std::endl;
    }

    void introduce() const {
        std::cout << "Hi, I'm " << name << " and I'm " << age << " years old." << std::endl;
    }
};

int main() {
    std::cout << "Creating initial vector:" << std::endl;
    std::vector<Person> people;
    
    std::cout << "\nAdding people to vector:" << std::endl;
    people.push_back(Person("Jhon", 35));
    people.emplace_back("Alice", 30);
    people.emplace_back("Bob", 25);
    
    std::cout << "\nVector size: " << people.size() << std::endl;
    
    std::cout << "\nCreating a copy of the vector:" << std::endl;
    std::vector<Person> people_copy = people;
    
    std::cout << "\nIntroducing people from original vector:" << std::endl;
    for (const auto& person : people) {
        person.introduce();
    }
    
    std::cout << "\nIntroducing people from copied vector:" << std::endl;
    for (const auto& person : people_copy) {
        person.introduce();
    }
    
    std::cout << "\nAdding a new person to original vector:" << std::endl;
    people.emplace_back("Charlie", 35);
    
    std::cout << "\nOriginal vector size: " << people.size() << std::endl;
    std::cout << "Copied vector size: " << people_copy.size() << std::endl;

    return 0;
}

Let's break down the key points:

  1. We define a Person class with a name and age.

  2. The class includes a regular constructor, a copy constructor, and a move constructor. Each constructor logs when it's called.

  3. In the main function, we create a vector of Person objects.

  4. We use emplace_back() to construct Person objects directly in the vector, which is more efficient than push_back() for non-trivial objects.

  5. We create a copy of the vector, which triggers the copy constructor for each Person object.

  6. We demonstrate that the original and copied vectors are independent by adding a new person to the original vector.

When you run this program, you'll see logs for each constructor call, allowing you to track when objects are being created, copied, or moved. This is particularly useful for understanding the behavior of vectors and optimizing performance.

Key observations from the output:

  1. When adding elements with emplace_back(), only the regular constructor is called.

  2. When creating a copy of the vector, the copy constructor is called for each element.

  3. The original and copied vectors are independent; changes to one don't affect the other.

This example showcases how vectors work with custom classes and highlights the importance of properly implementing constructors, especially when dealing with resource management in more complex classes.

PreviousCustom vector, part 3NextUnion

Last updated 9 months ago

🍡