 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
nthali Guest
|
Posted: Fri Jul 07, 2006 3:21 am Post subject: java guy struggling with C++ |
|
|
Hi,
I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a java style
List class, and did the same with the iterator. so my iterator looks
like this:
template <class T>
class Iterator
{
public:
Iterator( List<T> myList )
{
this->myList = myList._list;
started = false;
}
bool hasNext()
{
if ( myList.size() == 0 ) return false;
// for some reason unknown to me, i had to put the .begin()
and .end() check in the same method
// otherwise i get a core dumped.
if ( started == false ) { iter = myList.begin(); started =
true; }
return iter != myList.end();
}
T next()
{
return *iter++;
}
private:
bool started; // why the heck do i have to do this?
list<T> myList;
list<T>::iterator iter;
};
template <class T>
class List
{
friend class Iterator;
public:
void add(T obj);
T* get(int i);
int size();
Iterator<T> iterator();
T* toArray();
private:
list<T> _list;
};
The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
Thanks,
Nilesh
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Fri Jul 07, 2006 7:13 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
| Quote: | I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
[..]
template <class T
class Iterator
{
public:
Iterator( List<T> myList )
|
Here's your problem: you are copying a list. Remember, in Java, objects are
what would be a pointer/reference in C++!
| Quote: | The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
|
Sure, since you created a copy, that copy is not independent from the
original.
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Eugene Alterman Guest
|
Posted: Fri Jul 07, 2006 7:14 pm Post subject: Re: java guy struggling with C++ |
|
|
"nthali" <i.am.joatman (AT) gmail (DOT) com> wrote in message
news:1152204992.585568.272080 (AT) b68g2000cwa (DOT) googlegroups.com...
| Quote: | Hi,
I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a java style
List class, and did the same with the iterator.
|
Your first mistake is that you are trying to make your C++ code "Java-like".
It is understandable that you are much more comfortable with Java now, but
you have to be aware that C++ is a totally different language in spite of
some similarities. There is a good reason for differences in style and
idioms.
| Quote: | so my iterator looks
like this:
template <class T
class Iterator
{
public:
Iterator( List<T> myList )
{
this->myList = myList._list;
started = false;
}
|
That what I am talking about
A class type variable in C++ contains an object value - not a reference to
object like in Java. A List argument is passed by value. The Iterator
constructor does not get the original List object but its temporary copy.
Other than that, try to initialize non-static data members in the
member-initializer list instead of using assignment in the constructor body.
Also it would make sence to declare the constructor 'explicit' to prevent
implicit conversion.
[snip]
| Quote: |
The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Zara Guest
|
Posted: Fri Jul 07, 2006 7:15 pm Post subject: Re: java guy struggling with C++ |
|
|
On 6 Jul 2006 18:21:15 -0400, "nthali" <i.am.joatman (AT) gmail (DOT) com> wrote:
| Quote: | Hi,
I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a java style
List class, and did the same with the iterator. so my iterator looks
like this:
template <class T
class Iterator
{
public:
...
T next()
{
return *iter++;
}
...
The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
You need to use a concept that does not exist by itself in Java: the |
reference.
T& next() {
return *iter++;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Gopala Krishna A Guest
|
Posted: Fri Jul 07, 2006 7:15 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
| Quote: | T next()
{
return *iter++;
}
snip
The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
|
Nilesh, IMHO you should change return type of function next() to T& instead
of T i.e you should return a reference.
--
Gopala
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Lally Guest
|
Posted: Fri Jul 07, 2006 7:16 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
| Quote: | Hi,
I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a java style
List class, and did the same with the iterator. so my iterator looks
|
First and foremost: shame on you.
| Quote: | like this:
template <class T
class Iterator
{
public:
Iterator( List<T> myList )
{
this->myList = myList._list;
started = false;
}
bool hasNext()
{
if ( myList.size() == 0 ) return false;
// for some reason unknown to me, i had to put the .begin()
and .end() check in the same method
// otherwise i get a core dumped.
if ( started == false ) { iter = myList.begin(); started =
true; }
return iter != myList.end();
}
|
Store a copy of the list's end() iterator, and compare against that.
Do _not_ store a copy of the list in your iterator!
| Quote: |
T next()
{
return *iter++;
}
private:
bool started; // why the heck do i have to do this?
|
If you don't know why you have a random state bool like that, then step
through your code mentally. Or put in lots of debugging print
statements. It's a red flag for bad logic.
This makes a _copy_ of the list. It's not like a reference in Java.
| Quote: | list<T>::iterator iter;
};
[snip]
|
Please, just take out a sticky note and write down:
for (list<T>::iterator it = list.begin ();
it != list.end ();
++it) {
blah (*it);
}
Then put the sticky note somewhere you can see real easily. Trust me,
it'll make life easier.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Påhl Melin Guest
|
Posted: Fri Jul 07, 2006 7:16 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
| Quote: | Hi,
I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a java style
List class, and did the same with the iterator. so my iterator looks
like this:
|
[ ... snip ... ]
| Quote: | The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
|
The main problem is that you confuse the Java and C++ object model. In
C++ the list class is a value class (not a "reference" to the actual
object) which means that in your constructor for the Iterator class you
actually copy the whole list twice (first in function argument and then
in the assignment to the private Iterator myList variable) and then
traverses that second new list instead of the original list.
| Quote: | Iterator( List<T> myList )
{
this->myList = myList._list;
started = false;
}
|
If you hold the list in the Iterator class by pointer of reference
instead, it should fix the problem:
| Quote: | private:
bool started; // why the heck do i have to do this?
list<T>& myList; // *** by reference instead ***
list<T>::iterator iter;
|
....and in the constructor you take the list as a reference to avoid
copying the argument. Please note that I put the initialization of the
reference in the contructor's initialization list, before the
contructor body.
| Quote: | Iterator( const List<T>& iterateThisList )
: myList(iterateThisList)
{
started = false;
}
|
/ Påhl
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
James Hopkin Guest
|
Posted: Fri Jul 07, 2006 7:18 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
// reordered message
| Quote: | The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list, so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
|
The problem is that the iterator needs to store a reference to the
list. Your code is storing a copy. Here is an implementation of
Iterator that fixes the main problem and also doesn't need your
'started' bool:
#include <list>
template <class T> class List;
template <class T>
class Iterator
{
public:
Iterator(List<T>& myList)
: myList(myList)
, iter(myList.begin())
{
}
bool hasNext() const
{
return iter != myList.end();
}
T& next()
{
return *iter++;
}
private:
std::list<T>& myList;
typename std::list<T>::iterator iter;
};
Note the 'typename': it is required, although your compiler may have
let it pass.
| Quote: |
template <class T
class List
{
friend class Iterator;
public:
void add(T obj);
T* get(int i);
int size();
Iterator<T> iterator();
T* toArray();
private:
list<T> _list;
};
|
I won't comment too much on List itself, since you didn't provide the
implementation, but 'get' should probably return a reference and you'd
better think carefully about what toArray is doing (unlike vector, you
can't use the address of the first element of a list as an array).
James
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Fri Jul 07, 2006 7:18 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
| Quote: | I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a
java style List class, and did the same with the iterator.
|
Why? Java's collection classes embed different basic concepts
than the STL. One can argue about which is better; both have
certain qualities, and definite weaknesses. What one cannot
argue about is which is the idiomatic way of doing something in
the given language. Unless there are very severe constraints
for not doing something the C++ way in C++, it's better not to
fight the language.
Part of (re)learning C++ is learning the idioms necessary to use
the STL effectively.
| Quote: | so my iterator looks
like this:
template <class T
class Iterator
{
public:
Iterator( List<T> myList )
{
this->myList = myList._list;
started = false;
}
bool hasNext()
{
if ( myList.size() == 0 ) return false;
// for some reason unknown to me, i had to put the .begin()
and .end() check in the same method
// otherwise i get a core dumped.
if ( started == false ) { iter = myList.begin(); started =
true; }
return iter != myList.end();
}
T next()
{
return *iter++;
}
private:
bool started; // why the heck do i have to do this?
|
Good question. Why? Maybe because you don't initialize iter
in the constructor, like you should.
And this line is surely wrong. Your iterator contains a *copy*
of the list, and iterates through this copy. That is definitely
not the C++ way. Nor the Java way.
Note that you also pass the list by copy to the constructor, so
there's no way you can get anything but a copy in the iterator.
The usual C++ use of iterators does not require you to maintain
a reference to the container. It does require you to maintain
two iterators, however: a current position and the end position.
| Quote: | list<T>::iterator iter;
|
It also requires you to initialize this somehow. (And that's
not really different than in Java. In C++, if you use iter
before initialization, it's undefined behavior; in Java, it will
result in a NullPointerException, but neither corresponds to the
desired behavior.)
What's wrong with something like:
template< typename T >
class ListIterator
{
public:
explicit ListIterator( List< T >& list )
: myCurrent( list.asSTLList().begin() )
, myEnd( list.asSTLList().end() )
{
}
bool hasNext() const
{
return myCurrent != myEnd ;
}
T& next()
{
assert( hasNext() ) ;
return *myCurrent ++ ;
}
private:
list< T >::iterator myCurrent ;
list< T >::iterator myEnd ;
} ;
Note that:
1. The list is passed to the constructor by reference, not by
value. (In Java, everything's a pointer. This is not true
in C++, and you only get a level of indirection if you
explicitly request it.)
2. The class itself maintains two iterators. It could also
maintain a pointer to the list, and call end each time, but
why bother?
3. All of the members are initialized in the initialisation
list of the constructor. This is not an absolute necessity;
we could also assign them in the body of the constructor.
But it is a good habit to get into.
4. The constructor needs some way of getting at the underlying
STL list. For demonstration purposes, I used an explicit
member function, but in practice, if I didn't want to expose
the underlying STL list in List, I'd either make
ListIterator a friend of List, so that it could access the
underlying data member, or make List a friend of
ListIterator, then provide a private constructor which took
two std::list<T>::iterator.
5. As written, the class supports copy and assignment, by means
of the compiler generated defaults. If I really wanted to
*enforce* (and not just support) the Java idiom, I'd derive
from an Iterator<T> class, with hasNext() and next()
virtual, and the Iterator<T> class would declare a private
copy constructor and assignment operator, which it didn't
implement (or derive from boost::noncopiable).
| Quote: | template <class T
class List
{
friend class Iterator;
public:
void add(T obj);
T* get(int i);
int size();
Iterator<T> iterator();
T* toArray();
private:
list<T> _list;
};
The problem i have is: the next() method in the iterator
doesn't really give me the original object in the list, so
changing the values within that object don't change the
original object.
Anyone have any ideas on how to fix this?
|
Use pass by reference instead of pass by value.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Thomas Richter Guest
|
Posted: Fri Jul 07, 2006 7:19 pm Post subject: Re: java guy struggling with C++ |
|
|
nthali wrote:
| Quote: | Hi,
I switched from C++ to java about 5 years ago, and now i'm back doing
some C++.
here's briefly my problem:
I took the C++ stl list class, and tried to wrap it with a java style
List class, and did the same with the iterator.
|
First question: Why? It is IMHO better to think in the domain of the
language you're working with, and C++ style containers and iterators are
much more adapted to the C++ style of thinking than similar java
constructs. One could even argue that their use is considerably more
consistent, i.e. using operator++ for incrementing, and separating the
act of retrieving the element (by means of operator *) and incrementing
the iterator (by operator++).
| Quote: | template <class T
class Iterator
{
public:
Iterator( List<T> myList )
{
this->myList = myList._list;
started = false;
}
bool hasNext()
{
if ( myList.size() == 0 ) return false;
// for some reason unknown to me, i had to put the .begin()
and .end() check in the same method
// otherwise i get a core dumped.
|
Without seeing the program, hard to say. It should be sufficient to
start the iterator in the contructor. However, this means that for the
life-time of the iterator, modification of the list is forbidden. Maybe
you constructed the iterator first, then inserted elements into the
list? Likewise, the check for the size is unnecessary. For an empty
container, myList.begin() == myList.end().
| Quote: | if ( started == false ) { iter = myList.begin(); started =
true; }
return iter != myList.end();
}
T next()
{
return *iter++;
}
private:
bool started; // why the heck do i have to do this?
list<T> myList;
list<T>::iterator iter;
};
template <class T
class List
{
friend class Iterator;
public:
void add(T obj);
T* get(int i);
int size();
Iterator<T> iterator();
T* toArray();
private:
list<T> _list;
};
The problem i have is: the next() method in the iterator doesn't really
give me the original object in the list,
|
Well, it returns a copy, which is the C++ way of doing such things,
namely you're storing "values" in a list, not "objects". By retrieving a
list element, the value gets copied out of the list.
| Quote: | so changing the values within
that object don't change the original object.
Anyone have any ideas on how to fix this?
|
Ehem. From a C++ way of thinking, "don't fix, it ain't broken".
But maybe you'd like the following better:
The "next" member function should return a T&, not a T, i.e. a reference
such that you get an r-value for modification.
So long,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|