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. 8 2843
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
[...] 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
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
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
"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';
}
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
"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
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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 never changes.
This makes a std::list<> ideal for...
|
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 over 1K in size.
What methods of the std stl...
|
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>
#include <vector>
class Row
{
public:
|
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.
But std::list<const T*>::const_iterator doens't...
|
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 std::list;
template < class Contents class Tree_node{
...
|
by: TBass |
last post by:
So I have a class:
class Client
{
unsigned int ClientID;
....
};
class MyListenSocket
|
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:
maintainNeighbors.cpp:104: error: invalid initialization of...
|
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 &);
void pop_back();
|
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 here, according to the standard?
1) 'iter'...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
| |