0

I try to write a copy constructor for my vector of pointers to object initialized and declared in class Shop. The vector in consideration is:

std::vector <gCustomer*>   vCustomer;

It has been also declared in the constructor of gShop and deleted via loop in the destructor.

Now I want to have a deep copy of the vector of pointers in the copy constructor. But nothing gets actually copied, a check of its size remains zero or crashes the program if I manage to run the program and access vCustomer. (Note if I leave the copy constructor out so that the default copy constructor is used, the program runs fine)

gShop::gShop(const gShop & cShop)
    {
    for(int i = 0; i < (int)vCustomer.size(); ++i)
        {
        vCustomer[i]  = cShop.vCustomer[i];
        }
    }

Thanks

Note I also have an assigned operator

gShop gShop::operator=(const gShop & rhs)
   {
   if (this == &rhs) return *this;


    for(int i = 0; i < (int)vCustomer.size(); ++i)
        {
        delete vcustomer[i];
        vCustomer[i] = new gCustomer;
        vCustomer[i]= rhs.vCustomer[i];
        }
    }
CodeTrek
  • 435
  • 1
  • 3
  • 10
  • What version of C++ and what compiler do you use? Better use C++11, try [std::shared_ptr](http://www.cplusplus.com/reference/memory/shared_ptr/) i.e. `std::vector>` – Basile Starynkevitch Oct 12 '13 at 06:07
  • I cant use C++11.. somehow I cannot make it compile with my opengl stuff. I have downloaded boost, but I am not sure how to install it. I have GCC 4.3.5. – CodeTrek Oct 12 '13 at 06:08
  • Upgrade to a newer version of GCC. 4.3 is really old -before 2010- (and not C++11 standard conforming). Current [GCC](http://gcc.gnu.org/) is 4.8.1 (and 4.8.2 should appear within a week or two) – Basile Starynkevitch Oct 12 '13 at 06:10
  • It's all complicated.. I started the program 5 years ago.. it is really really large and has some opengl stuff. I am afraid it would be a lot of maintenance and rewriting if I would upgrade. Essentially when I tried GCC 4.8, my compiler says NO. And when I upgrade my compiler, my program says NO. – CodeTrek Oct 12 '13 at 06:13
  • I still think that going to C++11 (with a recent C++ compiler like GCC 4.8 or CLANG 3.3) is really worth the effort. How big is your program (millions of lines)? – Basile Starynkevitch Oct 12 '13 at 06:26
  • Is there any specific reason why you are using a `std::vector`? If you used a `std::vector` instead, all your problems should disappear as far as I can tell. – fredoverflow Oct 12 '13 at 06:30
  • I have some nested stuff and I cannot declare the object due to forward declaration error. TA pointer works because it assigns memory without knowing about the object beforehand. – CodeTrek Oct 12 '13 at 07:00
  • @Basile: Right now it is 12452 lines but it has some GLUT (some crappy experimental OPEN GL stuff that I've build on a few thing) so this makes it overly complicated – CodeTrek Oct 12 '13 at 07:12
  • 12KLOC is quite small these days. You definitely should take time to go to C++11 (which you can do progressively, since it is compatible with earlier standards). – Basile Starynkevitch Oct 12 '13 at 07:14

3 Answers3

1

The loop

gShop::gShop(const gShop & cShop)
    {
    for(int i = 0; i < (int)vCustomer.size(); ++i)
        {
        vCustomer[i]  = cShop.vCustomer[i];
        }
    }

uses the wrong limit. It should run from 0 to the length of the existing object:

i < (int)cShop.vCustomer.size()
urzeit
  • 2,863
  • 20
  • 36
  • 1
    Of course, when you do that, you also need to make sure vCustomer has enough elements to allow indexing it. Precede the loop with: vCustomer.resize(cShop.vCustomer.size()); – Mike Woolf Oct 12 '13 at 06:32
1

You've implemented your copy constructor and assignment operator wrongly, they are doing shallow copies not deep copies, and they don't resize the target vector. Here's a deep copy copy constructor

gShop::gShop(const gShop & cShop)
{
for(int i = 0; i < (int)cShop.vCustomer.size(); ++i)
    {
    if (cShop.vCustomer[i])
        vCustomer.push_back(new gCustomer(*cShop.vCustomer[i]));
    else
        vCustomer.push_back(NULL);
    }
}

and here's a deep copy assignment operator

gShop& gShop::operator=(const gShop & rhs)
{
if (this == &rhs) return *this;
// clear any existing data
for(int i = 0; i < (int)vCustomer.size(); ++i)
    delete vcustomer[i];
vcustomer.clear();
// add the new data
for(int i = 0; i < (int)rhs.vCustomer.size(); ++i)
    {
    if (rhs.vCustomer[i])
        vCustomer.push_back(new gCustomer(*rhs.vCustomer[i]));
    else
        vCustomer.push_back(NULL);
    }
return *this;
}

Basically the problem was that the you were copying pointers instead of allocating new memory. If you want a deep copy it's essential you allocate new memory.

Of course there is the bigger question, why are you using a vector of pointers at all. One of the big advantage of a vector is that you no longer have to explicitly manage memory, by using a vector of pointers you have lost that benefit. I don't know you program but it seems to me that std::vector<gCustomer> would be better than std::vector<gCustomer*>. With std::vector<gCustomer> you don't need to write a copy constructor or assignment operator, the deep copy will happen automatically (assuming gCustomer does a deep copy).

john
  • 85,011
  • 4
  • 57
  • 81
  • I am using a vector of pointers due to forward declaration reasons. I cannot initialize an object within that class, but I can initialize a pointer to that object. – CodeTrek Oct 12 '13 at 07:18
  • I copied it line for line. I am getting a segmentation fault and the debugger pinpoints that it crashes at vCustomer.push_back(new gCustomer(*cShop.vCustomer[i])) ?? – CodeTrek Oct 12 '13 at 07:25
  • OK, I realise that this probably isn't your biggest concern right now, but I don't think that's a valid reason. You should reorganise your code so that gCustomer is declared befre gShop. But yu've started down this path so I can see that you'll probably want to carry on. – john Oct 12 '13 at 07:25
  • It is not that easy I have 12k lines of code and dozends of classes and derivatives. Trying to figure out the combinatoric ranking of those classes that everything does not forward declare everything is not what I intend to do. – CodeTrek Oct 12 '13 at 07:27
  • @user2856452 That's probably because your gCustomer copy constructor is also bugged. I would guess you are getting all these problem because of inappropriate use of pointers. You are trying to do things the hard way. Post the gCustomer copy constructor and assignment operator if you are not sure. – john Oct 12 '13 at 07:27
  • No, that is the only instance I have pointers. All other classes use standard copy constructer. gCustomer has only one member function and a few ints. – CodeTrek Oct 12 '13 at 07:28
  • @user2856452 OK fair enough, that's more code than I expected, and it sounds like you are using inheritance which is a valid reason to use pointers. You should still prefer *smart pointers* to regular pointers however. – john Oct 12 '13 at 07:28
  • @user2856452 OK another try. Could your vector of pointers ever include a NULL pointer? My code would crash if that was true. Maybe you should add a check for that. – john Oct 12 '13 at 07:30
  • I love to.. I am trying the latest version of GCC right now (installing) and hope for it. But then again I never learn how to keep my memory clean... lol – CodeTrek Oct 12 '13 at 07:31
  • Ohh yes I should have said that I set it all to NULL in the initialization ;) At LEAST I want to make this work before I try to meddle with shared_ptr and give up on memory management. I owe it to myself lol – CodeTrek Oct 12 '13 at 07:34
  • I think you got a typo on the assignment operator too.. the loop should go to "rhs" or cShop in the declaration above – CodeTrek Oct 12 '13 at 07:38
  • @user2856452 Yes sorry, I'll fix it. I was a C programmer for many years, and spent a good portion of my time dealing with memory management issues. It was a huge relief when I learned C++ and realised I could isolate memory management from the rest of my code. Still have to deal with code written by people who don't know how to do this however. – john Oct 12 '13 at 07:41
  • OMG it compiled! I am so amazed that doing a copy constructor has revealed even more mistakes. When I left the standard copy constructor everything ran fine, now I also noticed another mistake later in the code where I had accessed [-1] as it crashed now here where it did not before – CodeTrek Oct 12 '13 at 08:02
  • So you say that when I have shr_ptr, all that memory stuff becomes easier to handle? I wouldn't bother about having a copy constructor? Should I really go for updating both my C++ and my code? – CodeTrek Oct 12 '13 at 08:04
  • @user2856452 If you use shared_ptr then you don't have to write your own copy constructor or assigment operator or destructor, the rule of three does not apply. This makes things much easier. However one caveat applies. If you use shared_ptr then you will get a shallow copy, when your shop class is copied you will end up with two shop objects both holding shared pointers to the same customers (the clue is in the name). Everything will still get freed correctly and you won't have any memory leaks but you will have shallow copies. Whether that's a problem for your application only you can say. – john Oct 12 '13 at 08:33
  • Ok I installed the latest GCC... I got only 39 errors and 142 warnings.. I might make it. Most errors say typeinfo before using typeid.. ? – CodeTrek Oct 12 '13 at 09:39
  • OK it works, I got it up and running. My problem is rather the old compiler (codeblocks) that errors on upgrade with my code. At least I have now shared_ptr! Thanks for all. I go with that! – CodeTrek Oct 12 '13 at 09:56
-1

std::vector<> has copy constructor itself to do the deep copy. So the copy constructor the compiler gives will do the work you want actually. If you want to implement it yourself, it's better in the init list of the constructor of gShop.

gShop::gShop(const gShop & cShop):vCustomer(cShop.vCustomer)
{
}

The size of vCustomer is always zero in your copy ctor.

I'm confused with your operator=(). What do you want? I suggest you read some text books about like c++ primer.

Zhongzhi
  • 436
  • 3
  • 6
  • It is mentioned in the rule of three: (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – CodeTrek Oct 12 '13 at 07:02
  • This answer is just wrong. The vector copy constructor does a shallow copy when it operates on a vector of pointers – john Oct 12 '13 at 07:03