tags:

views:

132

answers:

6

I have defined a class that contains a std::list as a member. When I create an object of that class, I expected the std::list to be empty. However, I queried the iterators returned by begin() and end() and found that they were not equal.

How can I ensure that my std::list member is empty on initial construction of the object?

Here is the code for my class:

typedef int ShapeHandle;
typedef void o_gadget;

class Gadget
{
public:
    Gadget( int c_id, int g_id, void * desc, size_t numbytes ):
        class_id(c_id), gadget_id(g_id)
        {
            memory = malloc( numbytes );
            father = 0;
            rightbro = 0;
            leftbro = 0;
            firstchild = 0;
            lastchild = 0;
            active = false;
            update = false;
        }
    void * memory;
    std::list<ShapeHandle> myshapes;
    std::list<o_gadget *> children;

    int class_id;
    int gadget_id;
    o_gadget * father;
    o_gadget * rightbro;
    o_gadget * leftbro;
    o_gadget * firstchild;
    o_gadget * lastchild;
    bool active;
    bool update;
};

I compared the iterators like this:

    ... 
    // search the tree stopping when we find the ID
Gadget * info = gadgets[from];
std::list<o_gadget *>::iterator iter = info->children.begin();
while( target == 0 && iter != info->children.end()  )
{
    FindGadget(ID, *iter, target);
    iter++;
}
    ... 

I didn't expect that on inspecting a new Gadget, that while loop would be entered. I know that target == 0 is true, so I figured that iter != info->children.end() was also true. However, I am not inspecting these values in a debugger.

EDIT

I'm so sorry everyone. This is clearly wrong. I've done it again. I've posted a bug that isn't actually there. I can't reproduce it now. Can you all vote to close it - or can I close this thing myself?

+5  A: 

The objects of std::list are created empty by default and therefore begin() should be equal to end().

I don't see anything wrong in your Gadget class and doing a simple check shows that the 'children' member variable is actually created empty:

#include <iostream>
#include <list>

class Gadget
{
// ...
};

int main()
{
    Gadget g(0, 0, 0, 0);
    std::cout << (g.children.begin() == g.children.end()) << std::endl;
}

It prints 1 because (begin() == end()) evaluates to true.

Were do you construct your 'gadgets' array?

vitaut
+2  A: 

Does list::empty() return TRUE for your freshly constructed list?

Blastfurnace
Lol an **answer** consisting of a single question... symbolic :)
Armen Tsirunyan
No, it probably returns `true` ;-)
Praetorian
+3  A: 

How are you determining that begin() and end() are returning different iterators? If you're inspecting their values in a debugger, that won't tell you much unless you know how operator== works on the iterators.

The empty() method can tell you directly if the list is empty or not.

Edit: The problem is almost certainly in the line Gadget * info = gadgets[from]; which is returning a pointer to either a Gadget containing some stuff that you didn't show us, or more likely is an invalid pointer altogether.

Mark Ransom
+1  A: 

Make sure all of the constructors of the parent class explicitly initialize the list member, either in their initializer-list or within their function bodies.

Loadmaster
+2  A: 

Newly constructed list (no constructor parameters) will be empty.

begin() and end() will not look identical in the debugger since they are both newly-constructed iterators on every call.

What do you mean by they are not equal? begin() == end() returns false, or something else?

Steve Townsend
+2  A: 

Here's a program that (for me) correctly prints "1", indicating that the iterators are equal. If you gradually change your program towards this program, the step at which it changes behavior might tell you what was wrong:

#include <iostream>
#include <list>
#include <cstdlib>

typedef int ShapeHandle;
typedef void o_gadget;

class Gadget
{
public:
    Gadget( int c_id, int g_id, void * desc, size_t numbytes ):
        class_id(c_id), gadget_id(g_id)
        {
            memory = std::malloc( numbytes );
            father = 0;
            rightbro = 0;
            leftbro = 0;
            firstchild = 0;
            lastchild = 0;
            active = false;
            update = false;
        }
    void * memory;
    std::list<ShapeHandle> myshapes;
    std::list<o_gadget *> children;

    int class_id;
    int gadget_id;
    o_gadget * father;
    o_gadget * rightbro;
    o_gadget * leftbro;
    o_gadget * firstchild;
    o_gadget * lastchild;
    bool active;
    bool update;
};

int main() {
    Gadget g(1,2,0,12);
    std::cout << (g.children.begin() == g.children.end()) << "\n";
}
Steve Jessop