User Tools

Site Tools


notes:stl_allocation_example

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
notes:stl_allocation_example [2013/02/25 17:01]
andy
notes:stl_allocation_example [2013/02/25 17:31]
andy
Line 130: Line 130:
 </​file>​ </​file>​
  
-===== std::map =====+===== std::​map ​(assignment) ​=====
  
-<code cpp stl_copy_map.cpp>+There are multiple ways to insert an item into a ''​std::​map''​ with subtly different memory copying behaviour. The code below shows a simple approach using assignment and array indexing syntax. 
 + 
 +<code cpp stl_copy_map_assign.cpp>
 #include <map> #include <map>
 #include <​stdio.h>​ #include <​stdio.h>​
Line 226: Line 228:
  
 ==== Typical Output ==== ==== Typical Output ====
 +
 +In contrast with the [[#​std::​list]] example above, ''​std::​map''​ invokes a substantial number of copy operations in the process of adding an element via assignment, as is done above.
 +
 +First, an in-place instance is constructed on the stack in response to the expression ''​MyClass(11)''​ as was done for ''​std::​list''​. Next, the default constructor is called to instantiate the instance in the map on the left-hand side of the assignment, and [[wikipedia>​placement new]] is used to copy this into the map --- there are two copies, presumably one being the creation of the ''​std::​pair''​ object to hold the key and value and the other to copy this again into the actual storage. At this point the destructors of both temporary instances are invoked. Then the assignment operator is used to overwrite the value in the map with the in-place instance created earlier. Finally, the destructor for the in-place instance is called, as with ''​std::​list''​.
  
 <​file>​ <​file>​
Line 283: Line 289:
 0x1edb0c4: ~MyClass(22) 0x1edb0c4: ~MyClass(22)
 0x1edb094: ~MyClass(21) 0x1edb094: ~MyClass(21)
 +</​file>​
 +
 +===== std::map (insert) =====
 +
 +As an alternative to using assignment, the ''​insert()''​ method can be used instead. This has the advantage that the class does not require a default constructor.
 +
 +<code cpp stl_copy_map_insert.cpp>​
 +#include <map>
 +#include <​stdio.h>​
 +
 +class MyClass
 +{
 +public:
 +  MyClass(int id);
 +  MyClass(const MyClass &​other);​
 +  ~MyClass();
 +  MyClass&​ operator=(const MyClass &​other);​
 +  int getID() const { return myID; }
 +private:
 +  MyClass();
 +  int myID;
 +};
 +
 +MyClass::​MyClass() : myID(-1)
 +{
 +  printf("​%p:​ MyClass()\n",​ this);
 +}
 +
 +MyClass::​MyClass(int id) : myID(id)
 +{
 +  printf("​%p:​ MyClass(%d)\n",​ this, myID);
 +}
 +
 +MyClass::​MyClass(const MyClass &other) : myID(other.myID)
 +{
 +  printf("​%p:​ MyClass(%p: MyClass(%d))\n",​ this, &other, myID);
 +}
 +
 +MyClass::​~MyClass()
 +{
 +  printf("​%p:​ ~MyClass(%d)\n",​ this, myID);
 +}
 +
 +MyClass&​ MyClass::​operator=(const MyClass &other)
 +{
 +  myID = other.myID;
 +  printf("​%p:​ MyClass = %p: MyClass(%d)\n",​ this, &other, myID);
 +
 +  return *this;
 +}
 +
 +
 +int main()
 +{
 +  std::​map<​int,​ MyClass> one;
 +  std::​map<​int,​ MyClass> two;
 +
 +  printf("​Adding 11 to one\n"​);​
 +  one.insert(std::​make_pair(11,​ MyClass(11)));​
 +  printf("​Adding 12 to one\n"​);​
 +  one.insert(std::​make_pair(12,​ MyClass(12)));​
 +  printf("​Adding 21 to two\n"​);​
 +  two.insert(std::​make_pair(21,​ MyClass(21)));​
 +  printf("​Adding 22 to two\n"​);​
 +  two.insert(std::​make_pair(22,​ MyClass(22)));​
 +
 +  printf("​Contents of one:​\n"​);​
 +  for (std::​map<​int,​ MyClass>::​iterator it = one.begin();​
 +       it != one.end(); ++it) {
 +    printf(" ​ %d: %d\n", it->​first,​ it->​second.getID());​
 +  }
 +  printf("​Contents of two:​\n"​);​
 +  for (std::​map<​int,​ MyClass>::​iterator it = two.begin();​
 +       it != two.end(); ++it) {
 +    printf(" ​ %d: %d\n", it->​first,​ it->​second.getID());​
 +  }
 +
 +  printf("​Calling one.swap(two)\n"​);​
 +  one.swap(two);​
 +
 +  printf("​Contents of one:​\n"​);​
 +  for (std::​map<​int,​ MyClass>::​iterator it = one.begin();​
 +       it != one.end(); ++it) {
 +    printf(" ​ %d: %d\n", it->​first,​ it->​second.getID());​
 +  }
 +  printf("​Contents of two:​\n"​);​
 +  for (std::​map<​int,​ MyClass>::​iterator it = two.begin();​
 +       it != two.end(); ++it) {
 +    printf(" ​ %d: %d\n", it->​first,​ it->​second.getID());​
 +  }
 +
 +  printf("​Clearing two\n"​);​
 +  two.clear();​
 +
 +  printf("​Exiting now\n"​);​
 +  return 0;
 +}
 +
 +</​code>​
 +
 +==== Typical output ====
 +
 +This approach requires one fewer operation than the assignment-based creation above. After the in-place instance is constructed,​ it is immediately copied via the copy constructor into the ''​std::​pair''​ and then again into the storage within the map. All three temporary instances are then deleted.
 +
 +<​file>​
 +Adding 11 to one
 +0x7fffc2b75f80:​ MyClass(11)
 +0x7fffc2b75eb4:​ MyClass(0x7fffc2b75f80:​ MyClass(11))
 +0x7fffc2b75ec4:​ MyClass(0x7fffc2b75eb4:​ MyClass(11))
 +0xdaa034: MyClass(0x7fffc2b75ec4:​ MyClass(11))
 +0x7fffc2b75ec4:​ ~MyClass(11)
 +0x7fffc2b75eb4:​ ~MyClass(11)
 +0x7fffc2b75f80:​ ~MyClass(11)
 +Adding 12 to one
 +0x7fffc2b75f90:​ MyClass(12)
 +0x7fffc2b75ed4:​ MyClass(0x7fffc2b75f90:​ MyClass(12))
 +0x7fffc2b75ee4:​ MyClass(0x7fffc2b75ed4:​ MyClass(12))
 +0xdaa064: MyClass(0x7fffc2b75ee4:​ MyClass(12))
 +0x7fffc2b75ee4:​ ~MyClass(12)
 +0x7fffc2b75ed4:​ ~MyClass(12)
 +0x7fffc2b75f90:​ ~MyClass(12)
 +Adding 21 to two
 +0x7fffc2b75fa0:​ MyClass(21)
 +0x7fffc2b75ef4:​ MyClass(0x7fffc2b75fa0:​ MyClass(21))
 +0x7fffc2b75f04:​ MyClass(0x7fffc2b75ef4:​ MyClass(21))
 +0xdaa094: MyClass(0x7fffc2b75f04:​ MyClass(21))
 +0x7fffc2b75f04:​ ~MyClass(21)
 +0x7fffc2b75ef4:​ ~MyClass(21)
 +0x7fffc2b75fa0:​ ~MyClass(21)
 +Adding 22 to two
 +0x7fffc2b75fb0:​ MyClass(22)
 +0x7fffc2b75f14:​ MyClass(0x7fffc2b75fb0:​ MyClass(22))
 +0x7fffc2b75f24:​ MyClass(0x7fffc2b75f14:​ MyClass(22))
 +0xdaa0c4: MyClass(0x7fffc2b75f24:​ MyClass(22))
 +0x7fffc2b75f24:​ ~MyClass(22)
 +0x7fffc2b75f14:​ ~MyClass(22)
 +0x7fffc2b75fb0:​ ~MyClass(22)
 +Contents of one:
 +  11: 11
 +  12: 12
 +Contents of two:
 +  21: 21
 +  22: 22
 +Calling one.swap(two)
 +Contents of one:
 +  21: 21
 +  22: 22
 +Contents of two:
 +  11: 11
 +  12: 12
 +Clearing two
 +0xdaa064: ~MyClass(12)
 +0xdaa034: ~MyClass(11)
 +Exiting now
 +0xdaa0c4: ~MyClass(22)
 +0xdaa094: ~MyClass(21)
 </​file>​ </​file>​
  
notes/stl_allocation_example.txt · Last modified: 2013/02/25 17:31 by andy