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. ATL / WTL / STL
  4. how does copy constructor works with vector::push_back

how does copy constructor works with vector::push_back

Scheduled Pinned Locked Moved ATL / WTL / STL
graphicsquestion
11 Posts 5 Posters 1 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.
  • A Ajax95

    I'm trying to figure out how exactly vector::push_back() creates objects. Looks like vector::push_back() will create a lot of copies by copy constructor and destruct a lot. In other words, if I need to put a counter in the copy constructor to monitor how many copy of the objects are created during the run, I will get a number which I don't exactly understand why. Can anybody explain why push_back() keep making copies and deleting copies? By running the following sample program, I supose to get 2,4,6,8,10 as output, but I get 21,22,23,24,25. Why is that? Thanks! class CVecTest { public: CVecTest() {m_intCount = ++m_classNumber;} CVecTest::CVecTest(const CVecTest &vec) {m_intCount = ++m_classNumber;} ~CVecTest(){}; static int m_classNumber; int m_intCount; }; int CVecTest::m_classNumber = 0; int main(int argc, char* argv[]) { vector vec; for (int i=0; i<5; i++) { CVecTest p; vec.push_back(p); } for (int i=0; i<5; i++) cout << vec[i].m_intCount << endl; return 0; } :confused:

    S Offline
    S Offline
    Stephen Hewitt
    wrote on last edited by
    #2

    All STL containers have value semantics and as such copy or assign elements. Steve

    N 1 Reply Last reply
    0
    • A Ajax95

      I'm trying to figure out how exactly vector::push_back() creates objects. Looks like vector::push_back() will create a lot of copies by copy constructor and destruct a lot. In other words, if I need to put a counter in the copy constructor to monitor how many copy of the objects are created during the run, I will get a number which I don't exactly understand why. Can anybody explain why push_back() keep making copies and deleting copies? By running the following sample program, I supose to get 2,4,6,8,10 as output, but I get 21,22,23,24,25. Why is that? Thanks! class CVecTest { public: CVecTest() {m_intCount = ++m_classNumber;} CVecTest::CVecTest(const CVecTest &vec) {m_intCount = ++m_classNumber;} ~CVecTest(){}; static int m_classNumber; int m_intCount; }; int CVecTest::m_classNumber = 0; int main(int argc, char* argv[]) { vector vec; for (int i=0; i<5; i++) { CVecTest p; vec.push_back(p); } for (int i=0; i<5; i++) cout << vec[i].m_intCount << endl; return 0; } :confused:

      J Offline
      J Offline
      Johann Gerell
      wrote on last edited by
      #3

      std::vector and its friends in the C++ standard library will copy an added element and store the copy, not the original. std::vector doesn't destroy a contained object - it's the object destructor that handles destruction when the std::vector goes out of scope. There's no container in the C++ standard library, which can share pointers that will be deleted when the last reference to them die. There are such alternatives in Boost[^] and Loki[^]. -- The Blog: Bits and Pieces

      A 1 Reply Last reply
      0
      • J Johann Gerell

        std::vector and its friends in the C++ standard library will copy an added element and store the copy, not the original. std::vector doesn't destroy a contained object - it's the object destructor that handles destruction when the std::vector goes out of scope. There's no container in the C++ standard library, which can share pointers that will be deleted when the last reference to them die. There are such alternatives in Boost[^] and Loki[^]. -- The Blog: Bits and Pieces

        A Offline
        A Offline
        Ajax95
        wrote on last edited by
        #4

        But what I expect is, when an object is inserted to a container, the container will call its copy constructor to make a copy and put into the container. Based on the result of my testing, looks like there are more than one copy of the object is created by copy constructor during the "push_back" process, and some of them got deleted, finnally only more copy remained and stored into the container. Looks like the insertion process is more complicated than just a value semantic.

        S J 2 Replies Last reply
        0
        • A Ajax95

          But what I expect is, when an object is inserted to a container, the container will call its copy constructor to make a copy and put into the container. Based on the result of my testing, looks like there are more than one copy of the object is created by copy constructor during the "push_back" process, and some of them got deleted, finnally only more copy remained and stored into the container. Looks like the insertion process is more complicated than just a value semantic.

          S Offline
          S Offline
          Stephen Hewitt
          wrote on last edited by
          #5

          Does this help? I suspect the additional copies may be the result of calling a function as in this example. ---------------- #include #include using namespace std; class CLogMe { public: CLogMe() { cout << "CLogMe()" << endl; } CLogMe(const CLogMe &) { cout << "CLogMe(const CLogMe &)" << endl; } CLogMe& operator=(const CLogMe &) { cout << "operator=(const CLogMe &)" << endl; return *this; } }; typedef vector LogMes; LogMes g_LogMes; void Function(CLogMe me) { g_LogMes.push_back(me); // CLogMe copy constructor called here. } int main(int argc, char* argv[]) { CLogMe me; // CLogMe constructor called here. Function(me); // CLogMe copy constructor called here. return 0; } Steve

          A J 2 Replies Last reply
          0
          • S Stephen Hewitt

            Does this help? I suspect the additional copies may be the result of calling a function as in this example. ---------------- #include #include using namespace std; class CLogMe { public: CLogMe() { cout << "CLogMe()" << endl; } CLogMe(const CLogMe &) { cout << "CLogMe(const CLogMe &)" << endl; } CLogMe& operator=(const CLogMe &) { cout << "operator=(const CLogMe &)" << endl; return *this; } }; typedef vector LogMes; LogMes g_LogMes; void Function(CLogMe me) { g_LogMes.push_back(me); // CLogMe copy constructor called here. } int main(int argc, char* argv[]) { CLogMe me; // CLogMe constructor called here. Function(me); // CLogMe copy constructor called here. return 0; } Steve

            A Offline
            A Offline
            Ajax95
            wrote on last edited by
            #6

            This is exactly what I tried. I found the copy constructor get called a lot of time. After 5 push_back, copy constructor get called 20 times, and destroyed 15 times.

            1 Reply Last reply
            0
            • A Ajax95

              But what I expect is, when an object is inserted to a container, the container will call its copy constructor to make a copy and put into the container. Based on the result of my testing, looks like there are more than one copy of the object is created by copy constructor during the "push_back" process, and some of them got deleted, finnally only more copy remained and stored into the container. Looks like the insertion process is more complicated than just a value semantic.

              J Offline
              J Offline
              Johann Gerell
              wrote on last edited by
              #7

              Ajax95 wrote:

              the container will call its copy constructor to make a copy and put into the container

              The compiler, if any, makes the copy ctor call.

              Ajax95 wrote:

              Based on the result of my testing, looks like there are more than one copy of the object is created by copy constructor during the "push_back" process

              Not strange at all. The documented fact for a container with value semantics is that a copy of an element is added. It's not stipulated that one and only one copy will be made during the process and that that single copy is the one to be added. In fact, if you had taken the time to step into the push_back code while debugging, you would have noticed that lots of temporary copies are created during the process, which ensures that the original data is not tampered with.

              Ajax95 wrote:

              some of them got deleted

              Of course, that's the temporary ones that goes out of scope at each call return.

              Ajax95 wrote:

              Looks like the insertion process is more complicated than just a value semantic.

              No. -- The Blog: Bits and Pieces

              1 Reply Last reply
              0
              • S Stephen Hewitt

                Does this help? I suspect the additional copies may be the result of calling a function as in this example. ---------------- #include #include using namespace std; class CLogMe { public: CLogMe() { cout << "CLogMe()" << endl; } CLogMe(const CLogMe &) { cout << "CLogMe(const CLogMe &)" << endl; } CLogMe& operator=(const CLogMe &) { cout << "operator=(const CLogMe &)" << endl; return *this; } }; typedef vector LogMes; LogMes g_LogMes; void Function(CLogMe me) { g_LogMes.push_back(me); // CLogMe copy constructor called here. } int main(int argc, char* argv[]) { CLogMe me; // CLogMe constructor called here. Function(me); // CLogMe copy constructor called here. return 0; } Steve

                J Offline
                J Offline
                Johann Gerell
                wrote on last edited by
                #8

                I'd say the additional copies comes from temporaries during the process of adding an element. -- The Blog: Bits and Pieces

                1 Reply Last reply
                0
                • S Stephen Hewitt

                  All STL containers have value semantics and as such copy or assign elements. Steve

                  N Offline
                  N Offline
                  Nemanja Trifunovic
                  wrote on last edited by
                  #9

                  Stephen Hewitt wrote:

                  All STL containers have value semantics

                  For the next version of C++ standard it is planned to add move semantics[^]. That would be :cool:


                  My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.

                  S 1 Reply Last reply
                  0
                  • N Nemanja Trifunovic

                    Stephen Hewitt wrote:

                    All STL containers have value semantics

                    For the next version of C++ standard it is planned to add move semantics[^]. That would be :cool:


                    My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.

                    S Offline
                    S Offline
                    Stephen Hewitt
                    wrote on last edited by
                    #10

                    In the mean time you can get these semantics by butting smart pointers in the container - Boost has many such pointers. Steve

                    1 Reply Last reply
                    0
                    • A Ajax95

                      I'm trying to figure out how exactly vector::push_back() creates objects. Looks like vector::push_back() will create a lot of copies by copy constructor and destruct a lot. In other words, if I need to put a counter in the copy constructor to monitor how many copy of the objects are created during the run, I will get a number which I don't exactly understand why. Can anybody explain why push_back() keep making copies and deleting copies? By running the following sample program, I supose to get 2,4,6,8,10 as output, but I get 21,22,23,24,25. Why is that? Thanks! class CVecTest { public: CVecTest() {m_intCount = ++m_classNumber;} CVecTest::CVecTest(const CVecTest &vec) {m_intCount = ++m_classNumber;} ~CVecTest(){}; static int m_classNumber; int m_intCount; }; int CVecTest::m_classNumber = 0; int main(int argc, char* argv[]) { vector vec; for (int i=0; i<5; i++) { CVecTest p; vec.push_back(p); } for (int i=0; i<5; i++) cout << vec[i].m_intCount << endl; return 0; } :confused:

                      A Offline
                      A Offline
                      Arvind Bharti
                      wrote on last edited by
                      #11

                      To avoid these extra copy constructor, call reserve function. like vec.reserve(5); Everytime you calls push_back, vector has to expand the memory block and copies the elements from the original to new memory block. Here comes the copy constructor in picture. As the size of vector increases, the number of calls of copy constuctor keeps on increasing(directly proportional to number of elements in vector).

                      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