STL lists as retrun value

  • Thread starter Christian Christmann
  • Start date
C

Christian Christmann

Hi,

here is my small program:

Header file:

Class myClass
{
public:
void function();
list< pair< Object1*, Object1*> > getList() const;
...
private:

typedef std::pair< Object1*, Object1* > mPairType;
list< mPairType > myList;
...
};


And the source file:

list< pair< Object1*, Object1*> > myClass:getList() const
{
return myList;
}


void myClass::function()
{
typedef std::pair< Object1*, Object1* > myType;
list< myType>::const_iterator it = getList().begin();

for ( ; it != getList().end(); ++it )
{
std::pair< Object1*, Object1* > myPairs = (*it);
}
}
....


When I run this program, I get segmentation faults in line
"std::pair< Object1*, Object1* > myPairs = (*it);".
When I instead replace the function getList() by a direct
access to member "myList", i.e.:

void myClass::function()
{
typedef std::pair< Object1*, Object1* > myType;
list< myType>::const_iterator it = myList.begin();

for ( ; it != myList.end(); ++it )
{
std::pair< Object1*, Object1* > myPairs = (*it);
}
}


Everything works fine.

I don't understand why the return value of getList() [ returns the STL list ]
is not the same as a direct access to the private class member "myList".

What do I have to change to access the private member function "myList"
by the public class function getList() ?

I appreciate any help.

Thank you.

Chris
 
V

Victor Bazarov

Christian said:
here is my small program:

It's not a program. It's lacking some important elements, which prevents
it from being a program. Next time either post _complete_ code, or don't
claim it's a program. Below is a *code fragment*.
Header file:

Class myClass

I suppose it is really

class myClass
{
public:
void function();
list< pair< Object1*, Object1*> > getList() const;
...
private:

typedef std::pair< Object1*, Object1* > mPairType;
list< mPairType > myList;
...
};


And the source file:

list< pair< Object1*, Object1*> > myClass:getList() const
{
return myList;

Here you're duplicating (copying) your list. Is it really necessary?
You could just return a const reference to it, no?
}


void myClass::function()
{
typedef std::pair< Object1*, Object1* > myType;

You already have a very similar typedef in your class. Why duplicate?
Just use 'mPairType' here.
list< myType>::const_iterator it = getList().begin();

'getList()' creates a temporary, which is _destroyed_ at the end of this
initialisation. 'it' is _invalid_ as soon as you reach the semicolon.
for ( ; it != getList().end(); ++it )
{
std::pair< Object1*, Object1* > myPairs = (*it);
}
}
...


When I run this program, I get segmentation faults in line
"std::pair< Object1*, Object1* > myPairs = (*it);".

See above.
When I instead replace the function getList() by a direct
access to member "myList", i.e.:

void myClass::function()
{
typedef std::pair< Object1*, Object1* > myType;
list< myType>::const_iterator it = myList.begin();

Of course. Now, the iterator is valid because the list itself is _still_
valid at this point (and as long as the 'myClass' object survives).
for ( ; it != myList.end(); ++it )
{
std::pair< Object1*, Object1* > myPairs = (*it);
}
}


Everything works fine.

I don't understand why the return value of getList() [ returns the STL list ]
is not the same as a direct access to the private class member "myList".

What do I have to change to access the private member function "myList"
by the public class function getList() ?

V
 
B

Bob Hairgrove

Hi,

here is my small program:

Header file:

Class myClass
{
public:
void function();
list< pair< Object1*, Object1*> > getList() const;
...
private:

typedef std::pair< Object1*, Object1* > mPairType;
list< mPairType > myList;
...
};


And the source file:

list< pair< Object1*, Object1*> > myClass:getList() const
{
return myList;
}


void myClass::function()
{
typedef std::pair< Object1*, Object1* > myType;
list< myType>::const_iterator it = getList().begin();

for ( ; it != getList().end(); ++it )
{
std::pair< Object1*, Object1* > myPairs = (*it);
}
}
...


When I run this program, I get segmentation faults in line
"std::pair< Object1*, Object1* > myPairs = (*it);".
When I instead replace the function getList() by a direct
access to member "myList", i.e.:

void myClass::function()
{
typedef std::pair< Object1*, Object1* > myType;
list< myType>::const_iterator it = myList.begin();

for ( ; it != myList.end(); ++it )
{
std::pair< Object1*, Object1* > myPairs = (*it);
}
}


Everything works fine.

I don't understand why the return value of getList() [ returns the STL list ]
is not the same as a direct access to the private class member "myList".

What do I have to change to access the private member function "myList"
by the public class function getList() ?

I appreciate any help.

Not too surprising, considering that getList() returns a temporary
list. Therefore, in this statement:

list< myType>::const_iterator it = getList().begin();

"it" is an iterator to a list which goes out of scope as soon as the
function call begin() returns.
 
C

Christian Christmann

Thank you for your answer.
'getList()' creates a temporary, which is _destroyed_ at the end of this
initialisation. 'it' is _invalid_ as soon as you reach the semicolon.

Now I see that 'getList()' returns a temporary copy of the list. But why
is the list destroyed at the end of the initialization?
In my opinition, the iterator 'it' should point to an empty list that has
just been created, but the list should still exist since there's still a
reference to it.

Chris
 
B

Bob Hairgrove

Thank you for your answer.



Now I see that 'getList()' returns a temporary copy of the list. But why
is the list destroyed at the end of the initialization?
In my opinition, the iterator 'it' should point to an empty list that has
just been created, but the list should still exist since there's still a
reference to it.

An iterator is never a reference because references cannot be
incremented, decremented or changed by adding or subtracting a value
in the way an iterator can be.

An iterator is more like a pointer, but it is also not really a
pointer, either. It is an object. Often, though, an iterator will be
implemented similarly to a pointer, although that isn't possible for
std::list (do you kno why?) But conceptually, you might think of it in
this particular instance as a kind of pointer.

Assume that begin() returned a pointer instead of an iterator. When
the object it points to is destroyed, you would have a dangling
pointer. You can also have a dangling iterator for similar reasons.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top