472,326 Members | 2,100 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,326 software developers and data experts.

std::list and a composite type ..

Consider:

# include <iostream>
using std::cout;
using std::cin;
using std::endl;

# include <list>
using std::list;

struct my_struct
{
std::string mName;
int mValue;
};

typedef std::list<my_struct> my_list;

int main()
{

my_list cc;
my_struct s;
s.mName = "Foo";
s.mValue = 42;
cc.push_back(s); // add contents

s.mName = "Bar";
s.mValue = 67;
cc.push_back(s); // add contents

my_list::iterator it(cc.begin());
for (; it != cc.end(); ++it)
{
cout << "Name = " << (*it).mName.c_str()
<< " Value = " << (*it).mValue << endl;
}

it = cc.begin();
for (; it != cc.end(); ++it)
{
if (it->mName == "Foo")
{
//cout << "found " << '\n';
//cc.erase(it); // exception. How do I erase "Foo"??
}
}

//my_struct* ptr = *it;

my_struct* ptr = new my_struct;
if (!ptr)
std::cerr << "memory allocation failure " << '\n';
it = cc.begin();
for (; it != cc.end(); ++it)
//ptr = it // assign contents of iterator to memory?

delete ptr;
}

The standard list container my_list holds a composite type my_struct.
At issue is the need to 'erase' Foo and it's corresponding value of
42. How do I achieve this?

ptr is a block of memory that's been allocated the sizeof my_struct.
Is it possible to 'assign' the contents of the iterator to that
memory? Silly though this may seem, a classmate/lab partner was
opting to do as such and I informed him. 1. Doesn't make sense and
2. I don't think that can be done.
Jul 22 '05 #1
8 2757
On 20 Jul 2004 10:41:15 -0700, ma740988 <ma******@pegasus.cc.ucf.edu>
wrote:
Consider:

# include <iostream>
using std::cout;
using std::cin;
using std::endl;

# include <list>
using std::list;

struct my_struct
{
std::string mName;
int mValue;
};

typedef std::list<my_struct> my_list;

int main()
{

my_list cc;
my_struct s;
s.mName = "Foo";
s.mValue = 42;
cc.push_back(s); // add contents

s.mName = "Bar";
s.mValue = 67;
cc.push_back(s); // add contents

my_list::iterator it(cc.begin());
for (; it != cc.end(); ++it)
{
cout << "Name = " << (*it).mName.c_str()
<< " Value = " << (*it).mValue << endl;
}

it = cc.begin();
for (; it != cc.end(); ++it)
{
if (it->mName == "Foo")
{
//cout << "found " << '\n';
//cc.erase(it); // exception. How do I erase "Foo"??
}
}

//my_struct* ptr = *it;

my_struct* ptr = new my_struct;
if (!ptr)
std::cerr << "memory allocation failure " << '\n';
it = cc.begin();
for (; it != cc.end(); ++it)
//ptr = it // assign contents of iterator to memory?

delete ptr;
}

The standard list container my_list holds a composite type my_struct.
At issue is the need to 'erase' Foo and it's corresponding value of
42. How do I achieve this?
Same way as you would erase anything from a list.

ptr is a block of memory that's been allocated the sizeof my_struct.
Is it possible to 'assign' the contents of the iterator to that
memory? Silly though this may seem, a classmate/lab partner was
opting to do as such and I informed him. 1. Doesn't make sense and
2. I don't think that can be done.


Yes it's possible (why you would want to do it is another matter) but

*ptr = *it;

The mistake you made in deleting from a list is not what you thought. Look
at the code again.

it = cc.begin();
for (; it != cc.end(); ++it)
{
if (it->mName == "Foo")
{
cout << "found " << '\n';
cc.erase(it); // exception. How do I erase "Foo"??
}
}

The erase is fine, that works, but what is the very next thing that
happens?

Answer

++it

When you erase something from a list (or anything else) using an iterator
you invalidate that iterator. You cannot use that iterator afterwards for
anything else.

Here is how you should have written the code

it = cc.begin();
while (it != cc.end())
{
if (it->mName == "Foo")
{
cout << "found " << '\n';
it = cc.erase(it);
}
else
{
++it;
}
}

list::erase returns an iterator to the next position.

john
Jul 22 '05 #2
[...]

ptr is a block of memory that's been allocated the sizeof my_struct.
Is it possible to 'assign' the contents of the iterator to that
memory? Silly though this may seem, a classmate/lab partner was
opting to do as such and I informed him. 1. Doesn't make sense and
2. I don't think that can be done.
Yes it's possible (why you would want to do it is another matter) but

*ptr = *it;


There's no correlation between the sizeof the memory allocated by new
and the length/memory block of the iterator? In other words, assume
we added(push_back's) some very large number of my_struct's to the
list.
Now I'd envision that care should be taken when assigning the contents
of the iterator to the memory allocated by new, since 'the large
number' of contents may not fit. Yes/No?


The mistake you made in deleting from a list is not what you thought. Look
at the code again.

it = cc.begin();
for (; it != cc.end(); ++it)
{
if (it->mName == "Foo")
{
cout << "found " << '\n';
cc.erase(it); // exception. How do I erase "Foo"??
}
}

The erase is fine, that works, but what is the very next thing that
happens?

Answer

++it

When you erase something from a list (or anything else) using an iterator
you invalidate that iterator. You cannot use that iterator afterwards for
anything else.


I overlooked this.

Thanks
Mark
Jul 22 '05 #3
On 20 Jul 2004 18:57:34 -0700, ma740988 <ma******@pegasus.cc.ucf.edu>
wrote:
[...]
>
> ptr is a block of memory that's been allocated the sizeof my_struct.
> Is it possible to 'assign' the contents of the iterator to that
> memory? Silly though this may seem, a classmate/lab partner was
> opting to do as such and I informed him. 1. Doesn't make sense and
> 2. I don't think that can be done.
Yes it's possible (why you would want to do it is another matter) but

*ptr = *it;


There's no correlation between the sizeof the memory allocated by new
and the length/memory block of the iterator? In other words, assume
we added(push_back's) some very large number of my_struct's to the
list.
Now I'd envision that care should be taken when assigning the contents
of the iterator to the memory allocated by new, since 'the large
number' of contents may not fit. Yes/No?


No. An iterator refers to a *single* item that has been added to the list,
and *it returns a reference to that single item. The number of items in
the list is irrelevant.

This is a new misunderstanding of iterators to me, so I not sure quite
what you are thinking, but clearly you've got some serious misconception
about what iterators are.


The mistake you made in deleting from a list is not what you thought.
Look
at the code again.

it = cc.begin();
for (; it != cc.end(); ++it)
{
if (it->mName == "Foo")
{
cout << "found " << '\n';
cc.erase(it); // exception. How do I erase "Foo"??
}
}

The erase is fine, that works, but what is the very next thing that
happens?

Answer

++it

When you erase something from a list (or anything else) using an
iterator
you invalidate that iterator. You cannot use that iterator afterwards
for
anything else.


Actually my statement is inaccurate. What happens is that when an item is
erased from an list, by any means, all iterators that refer to the erased
item become invalid. Iterators that refer to unerased items remain valid.

john
Jul 22 '05 #4
On Wed, 21 Jul 2004 06:59:27 +0100, John Harrison
<jo*************@hotmail.com> wrote:
On 20 Jul 2004 18:57:34 -0700, ma740988 <ma******@pegasus.cc.ucf.edu>
wrote:
[...]
>
> ptr is a block of memory that's been allocated the sizeof my_struct.
> Is it possible to 'assign' the contents of the iterator to that
> memory? Silly though this may seem, a classmate/lab partner was
> opting to do as such and I informed him. 1. Doesn't make sense and
> 2. I don't think that can be done.


Perhaps you meant the contents of the list, not the contents of the
iterator. Then your objection would make more sense (but still not be
valid).

#include <algorithm>

my_struct* ptr = new my_struct[cc.size()]; // enough room for the entire
list
std::copy(cc.begin(), cc.end(), ptr); // copy entire list to ptr

john
Jul 22 '05 #5
"John Harrison" <jo*************@hotmail.com> wrote in message news:<opsbg4srtd212331@andronicus>...
[...]
Perhaps you meant the contents of the list, not the contents of the
iterator. Then your objection would make more sense (but still not be
valid).
'contents of the list'. Thats correct. I tend to mix up C++
terminology quite often.
#include <algorithm>

my_struct* ptr = new my_struct[cc.size()]; // enough room for the entire
list
std::copy(cc.begin(), cc.end(), ptr); // copy entire list to ptr

Ah!! cc.size() is what I was missing. I knew there had to be a
connection between the size of the memory allocated and the size of
the list to be copied.
The previous version (ie. my_struct* ptr = new my_struct;) could lead
to problems.

One other question.
I recalled reading about the preferred use of std::fill to memset.
One of the prime arguments against memset - as i understood it -
revolved around memset limitation with respect to alignment on byte
boundaries.

For starters std::fill is memset under the hood when viewed from
Visual Studio 7 compiler. Secondly, how would I (couldn't find within
my text and online) std::fill a struct to - say 0.
So now.

struct my_struct
{
std::string mName;
int mValue1;
int mValue2;
};

typedef std::list<my_struct> my_list;

int main()
{
my_struct s;
/// try passing the address of the struct
//std::fill(&s, sizeof s, 0);
my_list cc;
/// try iterators
//std::fill(cc.begin(), cc.end(), 0);
memset (&s, 0, sizeof s);
cout << s.mName.c_str() << '\n';
cout << s.mValue1 << '\n';
cout << s.mValue2 << '\n';
}
Jul 22 '05 #6
On 21 Jul 2004 11:57:21 -0700, ma740988 <ma******@pegasus.cc.ucf.edu>
wrote:

One other question.
I recalled reading about the preferred use of std::fill to memset.
One of the prime arguments against memset - as i understood it -
revolved around memset limitation with respect to alignment on byte
boundaries.

For starters std::fill is memset under the hood when viewed from
Visual Studio 7 compiler.
That's not true in general, it might be true for particular types.
Secondly, how would I (couldn't find within
my text and online) std::fill a struct to - say 0.
So now.

struct my_struct
{
std::string mName;
int mValue1;
int mValue2;
};
That struct cannot be filled to 0 because it contains a std::string. It's
just not a meaningful thing to try and do. What do you think the value of
mName should be after you've filled it with 0?

Further std::fill is for sequences and arrays, it is not for individual
objects.


typedef std::list<my_struct> my_list;

int main()
{
my_struct s;
/// try passing the address of the struct
//std::fill(&s, sizeof s, 0);
my_list cc;
/// try iterators
//std::fill(cc.begin(), cc.end(), 0);
memset (&s, 0, sizeof s);
cout << s.mName.c_str() << '\n';
cout << s.mValue1 << '\n';
cout << s.mValue2 << '\n';
}


You are just getting undefined behaviour here. You cannot memset a string.

The C++ way of doing what I think you are trying to do is to use a
constructor.

struct my_struct
{
my_struct() : mValue1(0), mValue2(0) {}
std::string mName;
int mValue1;
int mValue2;
};

int main()
{
my_struct s;
cout << s.mName << '\n'; // prints empty line
cout << s.mValue1 << '\n'; // prints 0
cout << s.mValue2 << '\n'; // prints 0
}

The constructor ensures that every my_struct has defined values when it is
created.

john
Jul 22 '05 #7
"John Harrison" <jo*************@hotmail.com> wrote in message news:<opsbh4zyvz212331@andronicus>...

[snip]
struct my_struct
{
std::string mName;
int mValue1;
int mValue2;
};


That struct cannot be filled to 0 because it contains a std::string. It's
just not a meaningful thing to try and do. What do you think the value of
mName should be after you've filled it with 0?


Does this mean that you cannot

my_struct s = {0}; // works?

/david
Jul 22 '05 #8
On 21 Jul 2004 18:49:50 -0700, David Rubin <da********@warpmail.net> wrote:
"John Harrison" <jo*************@hotmail.com> wrote in message
news:<opsbh4zyvz212331@andronicus>...

[snip]
> struct my_struct
> {
> std::string mName;
> int mValue1;
> int mValue2;
> };


That struct cannot be filled to 0 because it contains a std::string.
It's
just not a meaningful thing to try and do. What do you think the value
of
mName should be after you've filled it with 0?


Does this mean that you cannot

my_struct s = {0}; // works?

/david


You can do it, and it will compile, but it results in a call to the
std::string constructor with a NULL pointer, which is undefined behaviour
as I recall.

You could do this

my_struct s = { "" };

john
Jul 22 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: Dave | last post by:
Hello all, After perusing the Standard, I believe it is true to say that once you insert an element into a std::list<>, its location in memory...
8
by: JustSomeGuy | last post by:
I need to write an new class derived from the list class. This class stores data in the list to the disk if an object that is added to the list is...
5
by: Eric Lilja | last post by:
Hello, consider this complete program (sorry, it's not minimal but I hope it's readable at least): #include <algorithm> #include <iostream>...
6
by: PengYu.UT | last post by:
Hi, Suppose I have a list which contains pointers. I want the pointer got by dereferencing the iterator be a pointer pointing to a const object....
7
by: alex221 | last post by:
In need to implement a tree structure in which every node has arbitrary number of children the following code has come into mind: using...
7
by: TBass | last post by:
So I have a class: class Client { unsigned int ClientID; .... }; class MyListenSocket
3
by: Ray D. | last post by:
Hey all, I'm trying to pass a list into a function to edit it but when I compile using g++ I continue to get the following error: ...
12
by: isliguezze | last post by:
template <class T> class List { public: List(); List(const List&); List(int, const T&); void push_back(const T &); void push_front(const T...
11
by: Juha Nieminen | last post by:
Assume we have this: std::list<Typelist1(10, 1), list2(20, 2); std::list<Type>::iterator iter = list1.end(); list1.swap(list2); What happens...
0
by: tammygombez | last post by:
Hey everyone! I've been researching gaming laptops lately, and I must say, they can get pretty expensive. However, I've come across some great...
0
by: concettolabs | last post by:
In today's business world, businesses are increasingly turning to PowerApps to develop custom business applications. PowerApps is a powerful tool...
0
better678
by: better678 | last post by:
Question: Discuss your understanding of the Java platform. Is the statement "Java is interpreted" correct? Answer: Java is an object-oriented...
0
by: CD Tom | last post by:
This happens in runtime 2013 and 2016. When a report is run and then closed a toolbar shows up and the only way to get it to go away is to right...
0
by: CD Tom | last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. ...
0
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.