0

In order to better understand copy constructors and move constructors, I wrote a source which logs every call of constructors/destructors clearly.

By pushing two different objects of my class in a vector, I realize that the first object is destroyed then replaced by a new one (calling the copy constructor). How can I avoid this?

Here is my code:

#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <algorithm>

#define title(args) std::cout << "------ " << args << " ------" << std::endl

//******************** struct X
struct X
{
    // Count objects having the same name:
    static std::map<std::string, int> counter;

    // For logging and for the counter:
    std::string name;
    int id;

    // Some data to be allocated:
    long *data;

    //******************** X(const std::string &s)
    X(const std::string &s) : name(s)
    {
        init();
        log("Constructor");
    }

    //******************** X(const X &x)
    X(const X &x) : name(x.name)
    {
        init();
        log("Copy constructor");
    }

    //******************** X(X &&x)
    X(X &&x) : name(x.name)
    {
        init();
        x.data = nullptr;
        log("Move constructor");
    }

    //******************** void init()
    void init()
    {
        data = new long();
        id = ++X::counter[name];
    }

    //******************** ~X()
    ~X()
    {
        log("Destructor");
        if (data != nullptr) {
            free(data);
        }
    }

    //******************** void log(const std::string &message="") const
    void log(const std::string &message="") const
    {
        std::cout << "   " << name << "-" << id << " " << message << std::endl;
    }
};

std::map<std::string, int> X::counter;


//********************  main ()
int main ()
{
    std::vector<X> v;

    title("Construction foobar");
    v.push_back(X("foo"));

    title("Construction superman");
    v.push_back(X("superman"));

    title("Show the vector");
    for (auto &x : v) {
        x.log();
    }

    title("Bye");

    return 0;
}

Here is the output:

------ Construction foobar ------
   foo-1 Constructor
   foo-2 Move constructor
   foo-1 Destructor
------ Construction superman ------
   superman-1 Constructor
   superman-2 Move constructor
   foo-3 Copy constructor             <== How can I avoid this ?
   foo-2 Destructor                   <==
   superman-1 Destructor
------ Show the vector ------
   foo-3
   superman-2
------ Bye ------
   foo-3 Destructor
   superman-2 Destructor

I don't understand why foo-2 is destroyed and foo-3 is created instead.

Here is what I would have expected:

------ Construction foobar ------
   foo-1 Constructor
   foo-2 Move constructor
   foo-1 Destructor
------ Construction superman ------
   superman-1 Constructor
   superman-2 Move constructor
   superman-1 Destructor
------ Show the vector ------
   foo-2
   superman-2
------ Bye ------
   foo-2 Destructor
   superman-2 Destructor
yolenoyer
  • 8,797
  • 2
  • 27
  • 61

0 Answers0