Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Generic C++ object/structure swap

Generic C++ object/structure swap

Scheduled Pinned Locked Moved C / C++ / MFC
c++questiondata-structuresperformance
5 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    scottk IntelligentSolutions com
    wrote on last edited by
    #1

    I developed a simple object swap template. I simply do a binary swap of the class/structure contents. Yet I know that the developers of the STL libraries do not implement swaps in this way. Their implementation will make copies (via a copy constructor) and then use an assignment operator - "operator=()". The reason I want to do swaps in this manner is because of the obvious efficiencies. For instance, if I wanted to swap two branches of two very large tree structures, the copy and assignment operations become prohibative. My question is in what instances does the code below NOT work? template void ObjectSwap(_Ty &obj1, _Ty &obj2) { // Don't swap on the same object if (&obj1 != &obj2) { char tmp[sizeof(_Ty)]; // create a memory buffer size_t sz = sizeof(_Ty); memcpy((void *) tmp, (const void *) &obj1, sz); memcpy((void *) &obj1, (const void *) &obj2, sz); memcpy((void *) &obj2, (const void *) tmp, sz); } } Scott K

    R G J 3 Replies Last reply
    0
    • S scottk IntelligentSolutions com

      I developed a simple object swap template. I simply do a binary swap of the class/structure contents. Yet I know that the developers of the STL libraries do not implement swaps in this way. Their implementation will make copies (via a copy constructor) and then use an assignment operator - "operator=()". The reason I want to do swaps in this manner is because of the obvious efficiencies. For instance, if I wanted to swap two branches of two very large tree structures, the copy and assignment operations become prohibative. My question is in what instances does the code below NOT work? template void ObjectSwap(_Ty &obj1, _Ty &obj2) { // Don't swap on the same object if (&obj1 != &obj2) { char tmp[sizeof(_Ty)]; // create a memory buffer size_t sz = sizeof(_Ty); memcpy((void *) tmp, (const void *) &obj1, sz); memcpy((void *) &obj1, (const void *) &obj2, sz); memcpy((void *) &obj2, (const void *) tmp, sz); } } Scott K

      R Offline
      R Offline
      Rein Hillmann
      wrote on last edited by
      #2

      I could see this working but it could lead to unexpected results if there are other pointers that point to the same object. I'm confused though: why not just swap the pointers to the objects instead of the objects themselves? If you want to swap two branches of a large tree structure, you simply swap the pointers that point to those branches.

      1 Reply Last reply
      0
      • S scottk IntelligentSolutions com

        I developed a simple object swap template. I simply do a binary swap of the class/structure contents. Yet I know that the developers of the STL libraries do not implement swaps in this way. Their implementation will make copies (via a copy constructor) and then use an assignment operator - "operator=()". The reason I want to do swaps in this manner is because of the obvious efficiencies. For instance, if I wanted to swap two branches of two very large tree structures, the copy and assignment operations become prohibative. My question is in what instances does the code below NOT work? template void ObjectSwap(_Ty &obj1, _Ty &obj2) { // Don't swap on the same object if (&obj1 != &obj2) { char tmp[sizeof(_Ty)]; // create a memory buffer size_t sz = sizeof(_Ty); memcpy((void *) tmp, (const void *) &obj1, sz); memcpy((void *) &obj1, (const void *) &obj2, sz); memcpy((void *) &obj2, (const void *) tmp, sz); } } Scott K

        G Offline
        G Offline
        Gary R Wheeler
        wrote on last edited by
        #3

        If an object contains one or more pointers to other objects, a simple bit-wise copy may not be what you want. Copy constructors and assignment operators let you do a so-called deep copy that addresses this. For example, suppose you have the following class:

        class Stuff {
        Stuff();
        ~Stuff();
        int number;
        char *string;
        };
        Stuff::Stuff()
        : number(0),
        string(new char[10])
        {
        strcpy(string,"Stuff");
        }
        Stuff::~Stuff()
        {
        delete []string;
        }

        A bit-wise copy of one Stuff object to another simply copies the pointer to the string member. If one of the objects is then deleted, the other object's string member now points to freed memory. With a deep copy, you can ensure that each instance of the Stuff object has its own copy of the string:

        class Stuff {
        Stuff();
        Stuff(const Stuff &stuff);
        ~Stuff();
        int number;
        char *string;
        };
        Stuff::Stuff()
        : number(0),
        string(new char[10])
        {
        }
        Stuff::Stuff(const Stuff &stuff)
        : number(stuff.number),
        string(new char[10])
        {
        strcpy(string,stuff.string);
        }
        Stuff::~Stuff()
        {
        delete []string;
        }


        Software Zen: delete this;

        S 1 Reply Last reply
        0
        • G Gary R Wheeler

          If an object contains one or more pointers to other objects, a simple bit-wise copy may not be what you want. Copy constructors and assignment operators let you do a so-called deep copy that addresses this. For example, suppose you have the following class:

          class Stuff {
          Stuff();
          ~Stuff();
          int number;
          char *string;
          };
          Stuff::Stuff()
          : number(0),
          string(new char[10])
          {
          strcpy(string,"Stuff");
          }
          Stuff::~Stuff()
          {
          delete []string;
          }

          A bit-wise copy of one Stuff object to another simply copies the pointer to the string member. If one of the objects is then deleted, the other object's string member now points to freed memory. With a deep copy, you can ensure that each instance of the Stuff object has its own copy of the string:

          class Stuff {
          Stuff();
          Stuff(const Stuff &stuff);
          ~Stuff();
          int number;
          char *string;
          };
          Stuff::Stuff()
          : number(0),
          string(new char[10])
          {
          }
          Stuff::Stuff(const Stuff &stuff)
          : number(stuff.number),
          string(new char[10])
          {
          strcpy(string,stuff.string);
          }
          Stuff::~Stuff()
          {
          delete []string;
          }


          Software Zen: delete this;

          S Offline
          S Offline
          Scott K
          wrote on last edited by
          #4

          Thanks, but my question was about swaping the contents of two objects. You are talking about copying an object - very different things. Using your example here is how you would manually swap the contents of two objects: class Stuff { Stuff(); ~Stuff(); void swap(Stuff &rhs): // Swap two objects int number; char *string; }; Stuff::Stuff() : number(0), string(new char[10]) { strcpy(string,"Stuff"); } Stuff::~Stuff() { delete []string; } void swap(Stuff &rhs) { int tmpNumber = number; number = rhs.number; rhs.number = tmpNumber; char *tmpString = string; string = rhs.string; rhs.string = tmpString; } This will work 100% of the time if the object can guarantee that it manages the allocation and destruction of the string memory. The code will obviuosly fail if the user somehow was able to assign stack allocated memory to the string pointer. In that case the Stuff destructor would try to delete a reference to stack memory - very bad thing to do. My question then boils down to why would not the following swap code not work? void swap(Stuff &rhs) { char tmp[sizeof(*this)]; memcpy((void *)tmp, (void *)this, sizeof(*this)); memcpy((void *)this, (void *)&rhs, sizeof(*this)); memcpy((void *)&rhs, (void *)tmp, sizeof(*this)); }

          1 Reply Last reply
          0
          • S scottk IntelligentSolutions com

            I developed a simple object swap template. I simply do a binary swap of the class/structure contents. Yet I know that the developers of the STL libraries do not implement swaps in this way. Their implementation will make copies (via a copy constructor) and then use an assignment operator - "operator=()". The reason I want to do swaps in this manner is because of the obvious efficiencies. For instance, if I wanted to swap two branches of two very large tree structures, the copy and assignment operations become prohibative. My question is in what instances does the code below NOT work? template void ObjectSwap(_Ty &obj1, _Ty &obj2) { // Don't swap on the same object if (&obj1 != &obj2) { char tmp[sizeof(_Ty)]; // create a memory buffer size_t sz = sizeof(_Ty); memcpy((void *) tmp, (const void *) &obj1, sz); memcpy((void *) &obj1, (const void *) &obj2, sz); memcpy((void *) &obj2, (const void *) tmp, sz); } } Scott K

            J Offline
            J Offline
            Jambolo
            wrote on last edited by
            #5

            Really what you are asking is, "Why can't you just change the memory location of an object?" The answer is that other objects may be referencing it. If you use memcpy, it is not possible for the affected pointers to be fixed, like they could if you used copy constructors and/or assignment operators. A linked-linked is a good example. If you swap nodes using memcpy, the list would become corrupted. Doing it the slow and safe way gives the objects the chance to reinsert themselves into the list correctly.

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups