Post

Lifetime

Inspired by one of Jason Turner’s videos I decided to create my own class that helps me better understand how objects behave in C++.

The implementation of such a class is quite simple - we just log information inside each of the special member functions, describing what is happening (constructors of various kinds, copy/move assignment operators and destructor).

For readability I decided to add a member to the class which we can set during object creation - it makes the console output much easier to follow.

Below is the implementation of the Lifetime object along with a few simple usage examples.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
struct Lifetime
{
    Lifetime() : name("for_default_constructor")
    {
        std::cout << "Lifetime(): " << name << std::endl;
    }

    Lifetime(const std::string& name) : name(name)
    {
        std::cout << "Lifetime(const std::string&): " << name << std::endl;
    }

    Lifetime(const Lifetime& other) : name(other.name)
    {
        std::cout << "Lifetime(const Lifetime&): " << name << std::endl;
    }

    Lifetime(Lifetime&& other) noexcept : name(std::move(other.name))
    {
        std::cout << "Lifetime(Lifetime&&): " << name << std::endl;
    }

    Lifetime& operator=(const Lifetime& other)
    {
        name = other.name;
        std::cout << "operator=(const Lifetime&): " << name << std::endl;
        return *this;
    }

    Lifetime& operator=(Lifetime&& other) noexcept
    {
        name = std::move(other.name);
        std::cout << "operator=(Lifetime&&): " << name << std::endl;
        return *this;
    }

    ~Lifetime()
    {
        std::cout << "~Lifetime(): " << name << std::endl;
    }

    std::string name;
};

int main()
{
    Lifetime lifetime1("lifetime1");
    Lifetime lifetime2("lifetime2");
    Lifetime lifetime3("lifetime3");

    lifetime2 = lifetime1;

    Lifetime lifetime4("lifetime4");
    lifetime3 = std::move(lifetime4);
    
    Lifetime lifetime5(Lifetime("lifetime4"));

    return 0;
}

Below is the output produced by the program.

1
2
3
4
5
6
7
8
9
10
11
12
  Lifetime(const std::string&): lifetime1
  Lifetime(const std::string&): lifetime2
  Lifetime(const std::string&): lifetime3
  operator=(const Lifetime&): lifetime1
  Lifetime(const std::string&): lifetime4
  operator=(Lifetime&&): lifetime4
  Lifetime(const std::string&): lifetime4
  ~Lifetime(): lifetime4
  ~Lifetime(): 
  ~Lifetime(): lifetime4
  ~Lifetime(): lifetime1
  ~Lifetime(): lifetime1

These are very simple examples, but once you start using this class in more advanced scenarios you’ll notice that it’s a really simple yet very effective way to better understand object lifetimes in C++.

This post is licensed under CC BY 4.0 by the author.