mardi 27 décembre 2022

efficient use of std::move to aggregate all object instances in a std container

I need to centrally accumulate certain entity creations in my program into a container and I want to use the efficiency of std::move with a move constructor to aggregate all entities created anwhere in the program into one container witout extra copying or instance allocations. Unfortunately using the most popular std::vector container brings with it vector internal management overhead ( or is that compiler implementation dependent??)

For example

class Item {
public :
  static int Count;
  int ID;

  Item() : ID(Count++)
  { cout<<"   Item CREATED - ID:"<<ID<<endl; }

  Item(const Item &itm) : ID(Count++)
  { cout<<"   Item COPY CREATED - (ID:"<<ID<<") <= (ID:"<<itm.ID<<")\n"; }

  Item(const Item &&itm) : ID(Count++)
  { cout<<"   Item MOVE CREATED - (ID:"<<ID<<") <= (ID:"<<itm.ID<<")\n"; }

  ~Item() { cout<<" Item DELETED - (ID:"<<ID<<") \n"; }
};

int Item::Count = 0;

void VectorOfItemTest() {
  std::vector<Item> ItemVec;

  for(int idx=0; idx<3; idx++) {
    std::cout<<" { loop "<<idx<<std::endl;
    Item itemInst;
    ItemVec.push_back(std::move(itemInst));
    std::cout<<" } "<<idx<<std::endl<<std::endl;
  }
}

produces output :

-----------------------------
 { loop 0
   Item CREATED - ID:0
   Item MOVE CREATED - (ID:1) <= (ID:0)
 } 0

   Item DELETED - (ID:0)
 { loop 1
   Item CREATED - ID:2
   Item MOVE CREATED - (ID:3) <= (ID:2)
   Item COPY CREATED - (ID:4) <= (ID:1)
   Item DELETED - (ID:1)
 } 1

   Item DELETED - (ID:2)
 { loop 2
   Item CREATED - ID:5
   Item MOVE CREATED - (ID:6) <= (ID:5)
   Item COPY CREATED - (ID:7) <= (ID:4)
   Item COPY CREATED - (ID:8) <= (ID:3)
   Item DELETED - (ID:4)
   Item DELETED - (ID:3)
 } 2

   Item DELETED - (ID:5)
   Item DELETED - (ID:7)
   Item DELETED - (ID:8)
   Item DELETED - (ID:6)

Is it possible to avoid the extra copy-s that causes matching delete-s inside the for loop?

Is there a container (or can we use std::vector in any way) where we get all loop outputs looking as follows ?

 { loop X
   Item CREATED - ID:X
   Item MOVE CREATED - (ID:X+1) <= (ID:X)
 } X
 Item DELETED - (ID:X)

I have looked at Why std::move is required to invoke move assign operator of std::vector Why does std::move copy contents for a rvalue or const lvalue function argument? and a few others here but its still not clear how I can use std::vector (or other containers) efficiently with using std::move.

I found a rejected question Hard time understanding object lifetime, copy, move constructor asking close to what I am referring to here I guess.

Aucun commentaire:

Enregistrer un commentaire