C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Listenelement löschen

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Andreas Volz
Guest





PostPosted: Thu May 27, 2004 8:56 pm    Post subject: Listenelement löschen Reply with quote



Hi,

ich hab folgende STL Liste:

typedef std::list < BenderRobot > BenderRobotList;
typedef std::list < BenderRobot >::const_iterator
BenderRobotList_iterator;
....
BenderRobotList brl1;
BenderRobotList_iterator brl_it, brl_end_it;
BenderRobot bender_robot;

brl_it = brl1.begin ();
brl_end_it = brl1.end ();
for (lc = 0; brl_it != brl_end_it; ++brl_it)
{
..
bender_robot = *brl_it;
...

if (delete)
brl1.erase (brl_it);
}

Ich laufe also eine Liste mit den Iteratorn durch und schaue mir die
Objekte an. Bei bestimmten Objekten markiere ich delete und möchte die
dann aus der Liste löschen und mit dem nächsten Objekt oben wieder
anfangen. Im Prinzip sollte das ja mit erase gehen, aber irgendwie
bekomme ich es nicht hin. Er wirft mir übelste Fehler im Zusammenhang
mit Templates raus die ich nicht verstehe:

BenderRobotContainer.cpp: In member function `void
BenderRobotContainer::setRobotControlList(RobotControlList*)':
BenderRobotContainer.cpp:88: error: no matching function for call to `
std::list<BenderRobot, std::allocator::erase(
BenderRobotList_iterator&)'
/usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/bits/list.tcc:1
01: error: candidates are: std::_List_iterator<_Tp, _Tp&, _Tp*>
std::list<_Tp, _Alloc>::erase(std::_List_iterator<_Tp, _Tp&, _Tp*>)
[with _Tp = BenderRobot, _Alloc = std::allocator<BenderRobot>]
/usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/bits/stl_list.h
:894: error: std::_List_iterator<_Tp, _Tp&, _Tp*>
std::list<_Tp, _Alloc>::erase(std::_List_iterator<_Tp, _Tp&, _Tp*>,
std::_List_iterator<_Tp, _Tp&, _Tp*>) [with _Tp = BenderRobot, _Alloc
= std::allocator<BenderRobot>]
make: *** [BenderRobotContainer.o] Fehler

Wie lösche ich also korrekt das aktuelle Element? Oder geht man mein
Vorhaben ganz anders an?

Gruß
Andreas

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Nikolaus Schulz
Guest





PostPosted: Fri May 28, 2004 1:07 am    Post subject: Re: Listenelement löschen Reply with quote



"Andreas Volz" <usenet-spam-trap (AT) brachttal (DOT) net> wrote:

Quote:
typedef std::list < BenderRobot > BenderRobotList; typedef std::list
BenderRobot >::const_iterator
BenderRobotList_iterator;
...
BenderRobotList brl1;
BenderRobotList_iterator brl_it, brl_end_it; BenderRobot bender_robot;

[snip]

Quote:
brl1.erase (brl_it);

Tip: der Iterator ist ein const_iterator.


Nikolaus

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Markus Breuer
Guest





PostPosted: Fri May 28, 2004 6:42 am    Post subject: Re: Listenelement löschen Reply with quote



Quote:
typedef std::list < BenderRobot > BenderRobotList;
typedef std::list < BenderRobot >::const_iterator
BenderRobotList_iterator;

Du verwendest hier einen const_iterator ...

Quote:
brl_it = brl1.begin ();
brl_end_it = brl1.end ();
for (lc = 0; brl_it != brl_end_it; ++brl_it)
{
..
bender_robot = *brl_it;
...

if (delete)
brl1.erase (brl_it);

.... den du hier natürlich nicht zum Löschemverwenden kannst. Das Löschen
ändert (löscht) das Objekt und ist demnach eine non-const Operation.

Gruß Markus

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Andreas Dunke
Guest





PostPosted: Fri May 28, 2004 6:45 am    Post subject: Re: Listenelement löschen Reply with quote

Andreas Volz wrote:

Quote:
typedef std::list < BenderRobot > BenderRobotList;
typedef std::list < BenderRobot >::const_iterator
BenderRobotList_iterator;
...
BenderRobotList brl1;
BenderRobotList_iterator brl_it, brl_end_it;
BenderRobot bender_robot;

brl_it = brl1.begin ();
brl_end_it = brl1.end ();
for (lc = 0; brl_it != brl_end_it; ++brl_it)
{
..
bender_robot = *brl_it;
...

if (delete)
brl1.erase (brl_it);
}

Ich laufe also eine Liste mit den Iteratorn durch und schaue mir die
Objekte an. Bei bestimmten Objekten markiere ich delete und möchte die
dann aus der Liste löschen und mit dem nächsten Objekt oben wieder
anfangen. Im Prinzip sollte das ja mit erase gehen, aber irgendwie
bekomme ich es nicht hin. Er wirft mir übelste Fehler im Zusammenhang
mit Templates raus die ich nicht verstehe:

Hallo Andreas. :-)

Du definierst Dein BenderRobotList_iterator als const_iterator und möchtest
ihn aber später doch ändern, sprich löschen. Laß das const weg, dann sollte
es funktionieren.

--
Andreas

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Werner Salomon
Guest





PostPosted: Fri May 28, 2004 8:03 am    Post subject: Re: Listenelement löschen Reply with quote

Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote

Quote:
Hi,

ich hab folgende STL Liste:

typedef std::list < BenderRobot > BenderRobotList;
typedef std::list < BenderRobot >::const_iterator
BenderRobotList_iterator;
Hallo Andreas,


beachte hier 'BenderRobotList_iterator' ist vom Typ const_iterator.
Mit diesem Iterator-Typ kannst Du nur lesend auf die Liste zugreifen!

Quote:
...
BenderRobotList brl1;
BenderRobotList_iterator brl_it, brl_end_it;
BenderRobot bender_robot;

brl_it = brl1.begin ();
brl_end_it = brl1.end ();
for (lc = 0; brl_it != brl_end_it; ++brl_it)
{
..
bender_robot = *brl_it;
...

if (delete)
brl1.erase (brl_it);
hier versuchst Du mit einem const_iterator die Liste zu ändern !
}

Ich laufe also eine Liste mit den Iteratorn durch und schaue mir die
Objekte an. Bei bestimmten Objekten markiere ich delete und möchte die
dann aus der Liste löschen und mit dem nächsten Objekt oben wieder
anfangen. Im Prinzip sollte das ja mit erase gehen, aber irgendwie
bekomme ich es nicht hin. Er wirft mir übelste Fehler im Zusammenhang
mit Templates raus die ich nicht verstehe:
... der Compiler hat Recht Wink


Quote:
[...]
Wie lösche ich also korrekt das aktuelle Element?
mit einem iterator (ohne const)


Quote:
Oder geht man mein Vorhaben ganz anders an?
Auch ja, Du hast noch einen wichtigen Punkt nicht beachtet, der erst

zur Laufzeit auftreten wird.

Nach dem Löschen darfst Du den Iterator nicht mehr verwenden also auch
nicht inkrementieren. Das Verhalten ist undefiniert!
erase liefert Dir einen neuen Iterator, der hinter das gelöschte
Element zeigt, das kann natürlich auch end() sein. Also die
for-Schleife sollte etwa so aussehen:
for (lc = 0 ; brl_it != brl_end_it; ) {
bender_robot = *brl_it;
if (delete) {
brl_it = brl1.erase (brl_it);
}
else
++brl_it;
}

Und das funktioniert auch nur bei std::list (und maps und sets? -
müßte ich nachschauen ..).
Der STL-Weg aus einem (sequentiellen) Container einen Satz Elemente zu
löschen geht über den remove_if-Algorithmus.
Das sieht in etwa so aus:

Du erstellst Dir selbst einen sogenannten Funktor (eine Klasse mit
operator()()), der eine bool zurückgibt. Als Parameter wird ein
BenderRobot erwartet, und true zurückgegeben, falls dieser gelöscht
werden soll.

class ZuLoeschen {
public:
ZuLoeschen( .. // Parameter kannst Du hier auch mitgeben
bool operator()( const BenderRobot& robot ) {
bool toDelete = ..; // f( robot )
return toDelete;
}
};

Aufruf:
// alle zu löschenden Elemente nach hinten in die Liste
std::list < BenderRobot >::iterator i =
std::remove_if( brl_it, brl_end_it, ZuLoeschen( .. ) );
// alles wirklich löschen
brl1.erase( i, brl_end_it );

Und das kanst Du auch mit einem std::vector<> machen.

Gruß
Werner

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Markus Schaaf
Guest





PostPosted: Fri May 28, 2004 8:32 am    Post subject: Re: Listenelement löschen Reply with quote

"Nikolaus Schulz" <microschulz (AT) web (DOT) de> schrieb:

Quote:
brl1.erase (brl_it);

Tip: der Iterator ist ein const_iterator.

Wobei der Funktionsparameter an dieser Stelle (im Std) überqualifiziert
ist. Warum sollte man nicht mit einem »const_iterator« das Element
benennen können, welches man löschen möchte? IIRC gibt's dazu auch ein
Issue bei der LWG. IMO ein echter Defekt, zumal es keinen Cast von
»const_iterator« auf »iterator« gibt (bei Zeigern schon). (Letzteres
halte ich auch für einen Fehler, unabhängig von ersterem.)

MfG

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Karl Heinz Buchegger
Guest





PostPosted: Fri May 28, 2004 9:43 am    Post subject: Re: Listenelement löschen Reply with quote

Werner Salomon wrote:
Quote:

Nach dem Löschen darfst Du den Iterator nicht mehr verwenden also auch
nicht inkrementieren. Das Verhalten ist undefiniert!
erase liefert Dir einen neuen Iterator, der hinter das gelöschte
Element zeigt, das kann natürlich auch end() sein. Also die
for-Schleife sollte etwa so aussehen:
for (lc = 0 ; brl_it != brl_end_it; ) {
bender_robot = *brl_it;
if (delete) {
brl_it = brl1.erase (brl_it);
}
else
++brl_it;
}

Leider nicht.
Du bist einer Extension Deines Compiler Herstellers aufgesessen.
erase liefert naemlich nichts zurueck.

Aber so gehts:

for (lc = 0 ; brl_it != brl_end_it; ) {
bender_robot = *brl_it;
if (delete) {
brl1.erase (brl_it++);
}
else
++brl_it;
}

--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Markus Breuer
Guest





PostPosted: Fri May 28, 2004 9:58 am    Post subject: Re: Listenelement löschen Reply with quote

Quote:
brl1.erase (brl_it);

Tip: der Iterator ist ein const_iterator.


Wobei der Funktionsparameter an dieser Stelle (im Std) überqualifiziert
ist. Warum sollte man nicht mit einem »const_iterator« das Element
benennen können, welches man löschen möchte? IIRC gibt's dazu auch ein
Issue bei der LWG. IMO ein echter Defekt, zumal es keinen Cast von
»const_iterator« auf »iterator« gibt (bei Zeigern schon). (Letzteres
halte ich auch für einen Fehler, unabhängig von ersterem.)

Ich kann deinen Einwand nachvollziehen und habe versucht, die Analogie
auf Zeiger umzusetzen:

void foo( const char* _obj )
{
delete _obj;
}

Überraschend: g++ 2.95 kompiliert das auf höchstem warning-level ohne
Einwände. Warum? Ich habe ein const-Objekt und delete ändert(löscht)
das Objekt.
Habe ich etwas in Sachen const-correctness übersehen oder ist das ein
Bug im Compiler?

Gruß Markus

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Andreas Volz
Guest





PostPosted: Fri May 28, 2004 10:02 am    Post subject: Re: Listenelement löschen Reply with quote

Am Fri, 28 May 2004 11:43:29 +0200 schrieb Karl Heinz Buchegger:

Quote:
Leider nicht.
Du bist einer Extension Deines Compiler Herstellers aufgesessen.
erase liefert naemlich nichts zurueck.

Aber so gehts:
[...]

Hm, von welchem Compiler redet du den? Beim g++ 3.3.2 gehen zumindest
beide Versionen. Wäre das beim VC.NET (da soll es nämlich auch laufen)
schief gegangen?

Gruß
Andreas

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Karl Heinz Buchegger
Guest





PostPosted: Fri May 28, 2004 10:38 am    Post subject: Re: Listenelement löschen Reply with quote

Markus Breuer wrote:
Quote:


Ich kann deinen Einwand nachvollziehen und habe versucht, die Analogie
auf Zeiger umzusetzen:

void foo( const char* _obj )
{
delete _obj;
}

Überraschend: g++ 2.95 kompiliert das auf höchstem warning-level ohne
Einwände. Warum? Ich habe ein const-Objekt und delete ändert(löscht)
das Objekt.
Habe ich etwas in Sachen const-correctness übersehen oder ist das ein
Bug im Compiler?


Das ist per Design so.

5.3.5 Delete

2 [...]
[Note: a pointer to a const type can be the operand of a delete-expression; it
is not necessary to cast away the constness of the pointer expression before
it is used as the operand of the delete-expression.]


--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Karl Heinz Buchegger
Guest





PostPosted: Fri May 28, 2004 11:32 am    Post subject: Re: Listenelement löschen Reply with quote

Andreas Volz wrote:
Quote:

Am Fri, 28 May 2004 11:43:29 +0200 schrieb Karl Heinz Buchegger:

Leider nicht.
Du bist einer Extension Deines Compiler Herstellers aufgesessen.
erase liefert naemlich nichts zurueck.

Aber so gehts:
[...]

Hm, von welchem Compiler redet du den? Beim g++ 3.3.2 gehen zumindest
beide Versionen. Wäre das beim VC.NET (da soll es nämlich auch laufen)
schief gegangen?

Aehm. Irgendwie hab ich da was durcheinander gebracht. Wie war das nur?
(C++ Standard PDF File auf, suchen, suchen, suchen )
Ach ja, bei assoziativen Containern liefert erase nichts zurueck. Bei
einer std::list ist aber alles in Butter (soviel zu: alle Container
verhalten sich gleich :-)

Den Returnwert von erase zu verwenden ist also in Ordnung (auch wenn
er nicht gebraucht wird, wie gezeigt)

--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Markus Schaaf
Guest





PostPosted: Fri May 28, 2004 11:41 am    Post subject: Re: Listenelement löschen Reply with quote

"Markus Breuer" <markus.breuer (AT) gmx (DOT) de> schrieb:

Quote:
Warum sollte man nicht mit einem »const_iterator« das Element
benennen können, welches man löschen möchte?

Ich kann deinen Einwand nachvollziehen und habe versucht, die Analogie
auf Zeiger umzusetzen:

void foo( const char* _obj )
{
delete _obj;
}

Diese Übertragung ist nicht ganz richtig. Die Rolle des Iterator beim
Löschen aus einem Container ist die eines Indixes (es gibt auch noch
einige andere Elementfunktionen, die Iteratoren als Index benutzen).
Das ist vergleichbar mit:

char* array[] = { new char[4], new char[4] };
...
delete array[1];

Dabei spielt die Constness des Index 1 in der letzten Zeile ja auch
keine Rolle.

Quote:
Überraschend: g++ 2.95 kompiliert das auf höchstem warning-level ohne
Einwände. Warum? Ich habe ein const-Objekt und delete ändert(löscht)
das Objekt.

Das würde ich eher als eine Spezialität von »delete« begreifen. Das
benutzt nämlich die gleichen Regeln wie der D'tor. Und den D'tor kannst
Du auch für ein konstantes Objekt aufrufen.

Nebenbei ist Dein Bsp. auch noch weiter speziell, indem es einen Zeiger
vom Typ »char const*« benutzt, der implizit nach »char*« konvertieren
würde, wenn er müßte.

MfG

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Markus Breuer
Guest





PostPosted: Sat May 29, 2004 8:39 am    Post subject: Re: Listenelement löschen Reply with quote

Quote:
Warum sollte man nicht mit einem »const_iterator« das Element
benennen können, welches man löschen möchte?

Ich kann deinen Einwand nachvollziehen und habe versucht, die Analogie
auf Zeiger umzusetzen:

void foo( const char* _obj )
{
delete _obj;
}


Diese Übertragung ist nicht ganz richtig. Die Rolle des Iterator beim
Löschen aus einem Container ist die eines Indixes (es gibt auch noch
einige andere Elementfunktionen, die Iteratoren als Index benutzen).
Das ist vergleichbar mit:

char* array[] = { new char[4], new char[4] };
...
delete array[1];

Den Iterator habe ich bislang nicht als Index gesehen und er muß
technisch umgesetzt auch nicht auf einem Index basieren. Eine Ausnahme
bildet der random_access iterator, ihn kann man mit einem Index benutzen.
Umgekehrt, da hast du recht, kann man einen Iterator auch als
Lesezeichen/Index auffassen. Aber warum darf der const_iterator
dann übergeben werden, wenn er nach dem Aufruf ungültig geworden ist?

Ich muss mein Verständnis von const_iterator/iterator noch einmal
gründlich überdenken...

In diesem Sinne,

Markus

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Markus Schaaf
Guest





PostPosted: Sat May 29, 2004 12:11 pm    Post subject: Re: Listenelement löschen Reply with quote

"Markus Breuer" <markus.breuer (AT) gmx (DOT) de> schrieb:

Quote:
Ich muss mein Verständnis von const_iterator/iterator noch einmal
gründlich überdenken...

Der Unterschied liegt im Aspekt als Zugriffsvermittler auf ein Objekt.
Einmal kann man nur konstante Operationen/Funktionen benutzen, einmal
alle. Aber in der Rolle als Zeiger/Benenner eines Objekts sollten sich
beide gleich verhalten. Für eine Funktion wie »container::erase«
/benennt/ der übergebene Iterator nur das zu löschende Objekt. Die
Änderung bezieht sich hier auf den Container selbst². Deshalb ist/
sollte einzig die »const«-Eigenschaft des Containers ausschlaggebend
(sein).

Als praktisches Beispiel, um das Problem zu demonstrieren: Nehmen wie
an, wir haben eine Funktion, die ein bestimmtes Element in einem Feld
sucht:

int const* FindSpecialElement( int const* begin, int const* end );

Sinnvollerweise haben wir die Parameter als »const_iterator«
deklariert, damit wir auch in konstanten Feldern suchen können.
Außerdem benötigt diese Funktion keinen schreibenden Zugriff aufs Feld.
Nun habe ich eine weitere Funktion, die genau dieses gefundene Element
verändern soll:

void IncSpecialElement( int* begin, int* end )
{
int* p = const_cast<int*>( FindSpecialElement( begin, end ) );
++(*p);
}

Das ist völlig in Ordnung, ich weiß ja, daß der zurückgelieferte Zeiger
auf ein veränderbares Objekt zeigt. Nur bei Std-Containern geht das
so nicht. Es gibt einen kleinen Trick, wenn man Random-Access-Iteratoren
hat: Man benutzt einfach echte Indices. Das macht z.B. »string« so.

MfG

²) Das ist wie das Löschen einer Datei in einem Verzeichnis: Man braucht
dazu Schreibrechte für das Verzeichnis, nicht für die Datei.

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.