efficient use of std::move to aggregate all object instances in a std container - c++11

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\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;
}
}
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 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.
[UPDATE 1] Using pointers : My existing code uses pointers which avoid extra allocation and copy. I am trying to eliminate pointer usage through out my code moving forward - hence this question. I will revert to pointers if this change doubles the memory allocations and copy-s.
[UPDATE 2] #MooingDuck suggestion of using std::deque solved this issue without the need for reserve() or noexcept move constructor. I was actually in the process of designing an array of std::vector wrapper to avoid std::vector resizing as I also need pointers to the entities remain valid to support legacy code. std::deque seems to do precisely that
"The storage of a deque is automatically expanded and contracted
as needed. Expansion of a deque is cheaper than the expansion of
a std::vector because it does not involve copying of the existing
elements to a new memory location. On the other hand, deques
typically have large minimal memory cost; a deque holding just one
element has to allocate its full internal array (e.g. 8 times the
object size on 64-bit libstdc++; 16 times the object size or 4096
bytes, whichever is larger, on 64-bit libc++)."
The deque test
void DequeOfItemTest() {
std::deque<Item> ItemDQ;
for(int idx=0; idx<3; idx++) {
std::cout<<" { deque loop "<<idx<<std::endl;
Item itemInst;
ItemDQ.push_back(std::move(itemInst));
Item &refToItem = ItemDQ[ItemDQ.size()-1];
Item *ptrToItem = &refToItem;
std::cout<<" } "<<idx<<std::endl;
}
}
This produces the same output now as I wanted - a single entity allocation on the stack followed by a single move into a container and a single delete of the stack allocation
-----------------------------
{ deque loop 0
Item CREATED - ID:0
Item MOVE CREATED - (ID:1) <= (ID:0)
} 0
Item DELETED - (ID:0)
{ deque loop 1
Item CREATED - ID:2
Item MOVE CREATED - (ID:3) <= (ID:2)
} 1
Item DELETED - (ID:2)
{ deque loop 2
Item CREATED - ID:4
Item MOVE CREATED - (ID:5) <= (ID:4)
} 2
Item DELETED - (ID:4)
Item DELETED - (ID:5)
Item DELETED - (ID:3)
Item DELETED - (ID:1)
-----------------------------
[Note] as suggested in the comments and answer below (and by VS2022) declaring move constructor and move assignment operators as noexcept is good practice as it lets containers like std::vector use the more efficient move operation instead of a copy operation.

There are two things required to get your stated ideal:
First, you'll have to mark your move constructor as noexcept. And if it then throws an exception, std::terminate is called, so it really must be designed so that it never throws.
Item(const Item &&itm) noexcept : ID(Count++)
{ cout<<" Item MOVE CREATED - (ID:"<<ID<<") <= (ID:"<<itm.ID<<")\n"; }
This gets you down to:
{ 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 MOVE 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 MOVE CREATED - (ID:7) <= (ID:3)
Item MOVE CREATED - (ID:8) <= (ID:4)
Item DELETED - (ID:3)
Item DELETED - (ID:4)
} 2
Item DELETED - (ID:5)
Item DELETED - (ID:6)
Item DELETED - (ID:7)
Item DELETED - (ID:8)
The only thing that has changed above is that your copies from before are turned into moves.
The reason this is needed is so that vector::push_back can maintain the strong exception guarantee from C++98/03. This means that if any exception is thrown during the push_back, there are no changes to the value of the vector.
Second, you need to reserve sufficient space in the vector so that push_back never needs to allocate a bigger buffer:
std::vector<Item> ItemVec;
ItemVec.reserve(3);
This gets you down to the ideal:
{ 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)
} 1
Item DELETED - (ID:2)
{ loop 2
Item CREATED - ID:4
Item MOVE CREATED - (ID:5) <= (ID:4)
} 2
Item DELETED - (ID:4)
Item DELETED - (ID:5)
Item DELETED - (ID:3)
Item DELETED - (ID:1)
When push_back is called with ItemVec.size() == ItemVec.capacity(), a new buffer is allocated, and all of the existing elements are moved to the new buffer ... unless your move constructor is not noexcept, in which case all of the existing elements are copied to the new buffer.

Related

Auto Increment ID in SQL [duplicate]

This question already has answers here:
Auto Increment after delete in MySQL
(18 answers)
Closed 12 months ago.
I want to know how can I make my SQL Database table give an ID starting from 0 and with every new add to check if there is an old ID free .
Exemple :
I added 10 items then I deleted almost everyone and I kept item with ID=5.
After adding a new item , it gets id 11 not 0.
Note : I'm editing my DB with Laravel API.
SQL AUTO INCREMENT adds 1 to the biggest incrementable column value.
To fill a free integer slot you need to check for it manually, but that kinda defeats the purpose of auto-incrementing.
Anyway here is how to check for the first free ID value:
function getUnusedId($ids_array)
{
$max_id = max($used_ids); // can be 25 for example
// [1:(id|1), 2:(id|2), 3:(id|3), 4:(id|5)] =>> ID 4 is missing
for($i = 1; $i <= $max_id; $i++){
if($used_ids[$i] > $i){
return $i;
}
}
return $max_id + 1; // You can echo that all IDs are used.
}
// The IDs must be ordered for this solution
$used_ids = Model::orderBy('id')->pluck('id')->toArray();
$free_id = getUnusedId($used_ids);

organization find all children algorithm

So i am creating a system where users are able to build their own organization structure meaning that all organizations will most likely be different.
My setup is that an organization consists of different divisions. In my division table i have a value called parent_id that points to a division who is the current divisions parent.
a setup might look something like this (Paint drawing)
as you can see from the drawing division 2 and 3 are children of division 1 therefore they both have the value parent_id = 1
division 4 is a child of id 2 and has two children (5 & 6)
now to the tricky part because of the structure in my system i need access to all children and the childrens children in my system depending on a root node.
So for example if i want to know all of the children of division 1 the result should be [2,3,4,5,6]
Now my question is. how will i find all children connected?
At first i thought something like this
root = 1;
while(getChildren(root) != null)
{
}
function getChildren(root)
{
var result = 'select * from division where parent_id = '+root;
if(result != null)
{
root = result;
}
return result;
}
please note this is only an example of using a while loop to get through the list
However this would not work when the result of the statement returns two children
So my question is how do i find all children of any root id with the above setup?
You could use a recursive function. Be careful, and keep track of the children you have found so if you run into them again you stop and error - otherwise you will end up in an infinite loop.
I don't know what language you are using, so here's some psuedocode:
create dictionaryOfDivisions
dictionaryOfDivisions.Add(currentDivision)
GetChildren(currentDivision)
Function GetChildren(thisDivision) {
theseChildren = GetChildrenFromDB(thisDivision)
For each child in theseChildren
If dictionaryOfDivisions.Exists(child)
'Oops, here's a loop! Error
Exit
Else
dictionaryOfDivisions.Add(child)
GetChildren(child)
End If
Next
}

How can I add/remove an element in a table/metatable? - Lua Script

Well, I know how to create a table/metatable with their initial values, but I don't know how to insert or remove an element after its creation. How can I do this using the best practice in Lua Script? Is there any kind of standart function to do this?
Here's just about every way of inserting and removing from Lua tables; firstly, for array-style tables:
local t = { 1, 2, 3 }
-- add an item at the end of the table
table.insert(t, "four")
t[#t+1] = 5 -- this is faster
-- insert an item at position two, moving subsequent entries up
table.insert(t, 2, "one and a half")
-- replace the item at position two
t[2] = "two"
-- remove the item at position two, moving subsequent entries down
table.remove(t, 2)
And for hash-style tables:
local t = { a = 1, b = 2, c = 3 }
-- add an item to the table
t["d"] = 4
t.e = 5
-- remove an item from the table
t.e = nil

Homework: Algorithm to determine the two most popular items in a shopping cart

I'm trying to determine the two most popular items in a user's shopping cart.
Each time the user adds or removes an item to/from the cart a function updatePopularity(Item item) is called which is passed a single argument referencing the object that was updated. Here is a snippet of the code:
private void updatePopularity(InventoryItem item)
{
InventoryItem tempItem;
if (mostPopular == null)
{
if (item.count > 0)
{
mostPopular = item;
mostPopularLabel.setText(MOST_POPULAR + " " + item.name);
}
}
else if (nextPopular == null)
{
if (mostPopular.name != item.name && item.count > 0)
{
nextPopular = item;
nextPopularLabel.setText(NEXT_POPULAR + " " + item.name);
}
}
else if (mostPopular.count < item.count)
{
tempItem = mostPopular;
mostPopular = item;
mostPopularLabel.setText(MOST_POPULAR + " " + item.name);
nextPopular = tempItem;
nextPopularLabel.setText(NEXT_POPULAR + " " + nextPopular.name);
}
else if (nextPopular.count < item.count)
{
nextPopular = item;
nextPopularLabel.setText(NEXT_POPULAR + " " + nextPopular.name);
}
else if (mostPopular.count == 0)
{
}
}
I'm getting all fumbled in the logic though because there are so many possible scenarios that can play out.
The end result should be:
At any given moment the two items with the highest quantities in the shopping cart should appear as the most popular.
If the second most popular ends up with a greater quantity, the two items should swap positions for most and next-most popular.
As items are removed from the cart, popularity should also be updated.
Finally, if there is only one popular item because of cart updates, I should reflect that.
Can anyone help me with how to go about logically mapping out the possibilities?
I'm currently taking a Discrete Mathematics class, but I'm not far enough in to attempt solving this on paper yet. I'm not asking for the code to be written out for me, but just some guidance into how one works through the logic without a mess of if statements that get super confusing.
The implementation I ended up using is not efficient but it works...
Each time an item is is added or removed from the cart, the inventory is scanned finding the first two occurrences of the most and second most popular items. Then, those items are compared to the current holders of most and second most popular. The tricky part was with the logic because if an item took first place, then the current item in first needs to get pushed to second. However, and if an item that was currently second got bumped to first, then the first item to have been tied for second needed to become second. I was trying to map out the logic on paper, but I just don't have the skills or knowledge to do that. I end up confusing myself. :)

How can I insert a row after the row that is now selected in a sorted table

this is more or less a duplicate of the ones below:
How can i sort java JTable with an empty Row and force the Empty row always be last?
http://www.java.net/node/645655
the only difference is that i would like to insert the new row after the row that is currently selected. the default behavior of DefaultRowSorter would sort immediately when the row is inserted, while what i need is to turn off sorting temporarily so that i could insert the row in a position that i specified, not a position from the sorter
i noticed that there were 2 links provided in How can i sort java JTable with an empty Row and force the Empty row always be last?, but they are not valid anymore, that's why i created this new question.
I copied completely DefaultRowSorter and TableRowSorter from JDK and changed insertInOrder() like below and it seems now working as I expected.
for (int i = 0; i < max; i++) {
if(sortOnInsert)
{
index = Arrays.binarySearch(current, toAdd.get(i));
if (index < 0) {
index = -1 - index;
}
}
else
{
Row rowBeforeAdd = new Row(this, toAdd.get(i).modelIndex - 1);
index = Arrays.binarySearch(current, rowBeforeAdd);
if (index < 0) {
index = viewToModel.length - 1;
}
else
{
index += 1;
}
}

Resources