Thread: Works outside of the loop, not within

  1. #1
    Moderately Rabid Decrypt's Avatar
    Join Date
    Feb 2005
    Location
    Milwaukee, WI, USA
    Posts
    300

    Works outside of the loop, not within

    I don't even know what to search under to find the answer to this one...
    For pointer practice, I'm making a mancala game. To test the classes I made, I'm trying to create a game board and set it up before I get to making the game itself.
    I create two kinds of "buckets", end and middle. There are two ends, the rest of the board are middle buckets. (the only difference is that middle buckets start with some stones in them.)

    Each bucket has a member (a pointer) that points to the next bucket down the line. the Bucket::link(Bucket) function sets the pointer to the address of the Bucket passed to it.

    When setting up the board, I push end onto the vector. Then I add the rest onto the vector in a loop:
    Code:
    buckets.push_back(end);
    
    for (int fill = 1; fill != totalBuckets; ++fill)
    {
      if (fill == (totalBuckets \ 2)
        buckets.push_back(end);
      else
        buckets.push_back(middle);
    
      buckets[fill].link( buckets[fill - 1] );
    }
    
    for (int linker = 1; linker != totalBuckets; ++linker)
      buckets[linker].link( buckets[linker - 1] );
    
    buckets[0].link( buckets[buckets.size() - 1] )
    If I use the code in blue instead of green, only buckets[0] and the last half (8-13) of the buckets link correctly. The first half are linked all over the place (later in the setup function it prints the address of each bucket and the address pointed to by a member of each bucket.)

    If I use the green code instead of the blue, everything links up correctly. It looks like it's doing the same thing to me, but clearly that's not the case. I can also replace totalBuckets with buckets.size() and everything still works.

    As I said, to me, it seems that the green and blue statements are identical, one is done each time through the loop as the vector is being created, and the other is done after the vector is full. I know that vectors don't behave quite the way I usually expect them to, but I don't think that adding a member changes the other members, so I really have no clue what's going on here.

    On one hand, hey - it works now! However, I'd really like to know why.
    There is a difference between tedious and difficult.

  2. #2
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    If you push_back() something into a vector the objects might get reallocated. So the links will eventually point to buckets that don't exist anymore. Could work if you initally create the vector with the right size.
    Try printing the addresses of the buckets just after pushing them back and after all of them are inserted into the vector
    Kurt

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Adding the following line of code before the loop will fix the problem:
    Code:
    buckets.reserve(totalBuckets);

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Each bucket has a member (a pointer) that points to the next bucket down the line. the Bucket::link(Bucket) function sets the pointer to the address of the Bucket passed to it.

    I would not do this at all because of the dangers of the pointer being incorrect if the vector is reallocated. Instead, you could store an index, which is slightly more persistent than a pointer, although you would need to have access to the buckets vector to use that index. You could also store dynamically allocated bucket pointers in your vector. No matter how often the vector is reallocated or is contents rearranged, the pointer will remain valid. The problem with that is that you still have to be careful with the lifetime of the pointer and you need to delete the pointers yourself when you are done. Finally, the almost standard shared_ptr or boost's ptr_vector might help avoid that last issue.

  5. #5
    Moderately Rabid Decrypt's Avatar
    Join Date
    Feb 2005
    Location
    Milwaukee, WI, USA
    Posts
    300

    Lightbulb Thanks!

    Ahhhhhhh.

    Let me make sure I have this straight: While in the loop it's linking fine, but since g++ implements a vector by allocating enough space for only a few elements, then requests more space if more is needed, the pointers are no longer pointing to the correct Bucket because the vector has been moved to a contiguous space in memory big enough for the vector to fit, and the pointers cannot be adjusted accordingly. (How's that for a run-on sentence?) This also explains why when I was debugging w/gdb, the buckets would point to the "wrong" address, but still point at a Bucket object. (I assume, then, that the program doesn't clean up after itself when the vector is reallocated.)

    If I understand correctly, I have four options:

    1) resize/reserve the vector beforehand
    2) use a vector of pointers
    3) the way I found earlier
    4) shared_ptr or ptr_vector

    For this application, the vector will never change size once the board is set up, so I won't have to worry about reallocation after the fact. That's the way I feel most comfortable with now, (using 1 or 4) so I'll just go with that. Maybe I'll fiddle with the others later. I'll definately look into shared_ptr and ptr_vector, since I have no clue what they are.

    Thanks for the responses!
    There is a difference between tedious and difficult.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> For this application, the vector will never change size once the board is set up, so I won't have to worry about reallocation after the fact.

    In that case option 1 is certainly a good way to go, IMO.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. My loop within loop won't work
    By Ayreon in forum C Programming
    Replies: 3
    Last Post: 03-18-2009, 10:44 AM
  2. return to start coding?
    By talnoy in forum C++ Programming
    Replies: 1
    Last Post: 01-26-2006, 03:48 AM
  3. loop needed also how to make input use letters
    By LoRdHSV1991 in forum C Programming
    Replies: 3
    Last Post: 01-13-2006, 05:39 AM
  4. Loop, Loop, Loop?!
    By aprilbiz in forum C Programming
    Replies: 10
    Last Post: 07-24-2002, 04:45 AM
  5. How to change recursive loop to non recursive loop
    By ooosawaddee3 in forum C Programming
    Replies: 1
    Last Post: 06-24-2002, 08:15 AM