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 

const Problem mit Kontainern von Pointern

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





PostPosted: Thu Jun 17, 2004 8:51 am    Post subject: const Problem mit Kontainern von Pointern Reply with quote



Hallo,

auch folgendes Problem hat mit constness zu tun:


void doSomething(const vector<int *>& v)
{
*v[0] = 0;
}

int main()
{
vector<int*> vi;

doSomething(vi);

return 0;
}

Ich möchte aber auch unterbinden, daß die Inhalte auf die die Pointer in v
zeigen geändert werden. Also:

void doSomething(const vector<const int *>& v)
{
*v[0] = 0; // nicht mehr erlaubt
}

Aber nun kann vi nicht mehr übergeben werden. Und den vector umzukopieren,
kann ja wohl nicht die Lösung sein! Übersehe ich da etwas oder ist das eine
Schwachstelle von C++?

TIA,

Tobias

--
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
Helmut Zeisel
Guest





PostPosted: Thu Jun 17, 2004 3:25 pm    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote



Tobias Wollgam wrote:

Quote:
Hallo,

auch folgendes Problem hat mit constness zu tun:


void doSomething(const vector<int *>& v)
{
*v[0] = 0;
}

int main()
{
vector<int*> vi;

doSomething(vi);

return 0;
}

Ich möchte aber auch unterbinden, daß die Inhalte auf die die Pointer in v
zeigen geändert werden. Also:

void doSomething(const vector<const int *>& v)
{
*v[0] = 0; // nicht mehr erlaubt
}

Aber nun kann vi nicht mehr übergeben werden. Und den vector umzukopieren,
kann ja wohl nicht die Lösung sein! Übersehe ich da etwas oder ist das eine
Schwachstelle von C++?

So weit ich sehe, ist die von Dir gewuenschte Umwandlung tatsaechlich
sicher. Leider enthaelt std::vector keine Regeln, wann die Umwandlung
von vector<A> auf vector<B> sicher ist - diese Regeln automatisch per
Templates zu erkennen ist sicher keine triviale Aufgabe.

Fuer Dich gibt es dann wohl nur die Moeglichkeit, entweder auch vi als
vector<const int*> anzulegen oder die Schnittstelle von doSomething zu
aendern, z.B:

typedef vector<int*> tVec;
void doSomething(const int* const* v, tVec::size_type n);

int main()
{
vector<int*> vi;
doSomething(&vi[0],vi.size());
...
}

Du musst hier leider abwaegen, ob Du lieber klaren und sicheren oder
effizienten Code haben willst. Im Normalfall solltest Du Sicherheit
vorziehen, also tatsaechlich zuerst auf einen vector<const int*> kopieren.

Helmut

--
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
Falk Tannhäuser
Guest





PostPosted: Thu Jun 17, 2004 5:52 pm    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote



Tobias Wollgam wrote:
Quote:

void doSomething(const vector<int *>& v)
{
*v[0] = 0;
}

int main()
{
vector<int*> vi;
doSomething(vi);
return 0;
}

Ich möchte aber auch unterbinden, daß die Inhalte auf die die Pointer in v
zeigen geändert werden. Also:

void doSomething(const vector<const int *>& v)
{
*v[0] = 0; // nicht mehr erlaubt
}

Aber nun kann vi nicht mehr übergeben werden. Und den vector umzukopieren,
kann ja wohl nicht die Lösung sein! Übersehe ich da etwas oder ist das eine
Schwachstelle von C++?

Du bräuchtest also die Möglichkeit, ein Objekt vom Typ 'vector<int*>' wie
einen 'vector<int const*>' zu behandeln. C++ bietet keine standardkonforme
Möglichkeit an, dies zu bewerkstelligen. Würde eine solche Möglichkeit
bestehen, würde sie die Verletzung der const-Korrektheit ermöglichen!
Beispiel:

std::vector<int*> vi;

// ACHTUNG - dreckig! Kinder, probiert das nicht zu Hause aus!
std::vector<int const*>& vci = reinterpret_cast<std::vector(vi);
// Alle folgenden Zugriffe auf vci sind Nicht Definiertes Verhalten,
// sollten aber überall dort "wie erwartet" funktionieren, wo
// 'vector<int*>' und 'vector<int const*>' das gleiche Speicherlayout haben.

doSomething(vci); // Das geht BEI MIR noch ganz wie gewünscht

static int const n = 42;
//vi.push_back(&n); // Das ließe der Compiler nicht durchgehen
vci.push_back(&n);

std::cout << *vi.back() << std::endl; // Das geht auch noch

++*vi.back(); // "Signal 11" und tschüss bei mir (Compiler: gcc 3.3.1 CygWin)
std::cout << *vi.back() << ' ' << n << std::endl;


Das hier ist bezüglich const-Korrektheit sicher, doch ansonsten ebenfalls nicht
vom Standard garantiert:
std::vector(vi);
Zumindest in wichtigem Kode würde ich davon die Finger lassen.

Ein analoges Problem gibt es übrigens mit Zeigerzeigern - da gestattet der Standard
aber ausdrücklich (siehe 4.4/4) die sicheren Umwandlungen:

int** ppi = 0;
int const** ppci = ppi; // Verboten
int const* const* pcpci = ppi; // Erlaubt

MfG
Falk

--
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
helmut zeisel
Guest





PostPosted: Thu Jun 17, 2004 6:36 pm    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote

Falk Tannhäuser wrote:

Quote:
Du bräuchtest also die Möglichkeit, ein Objekt vom Typ 'vector<int*>' wie
einen 'vector<int const*>' zu behandeln. C++ bietet keine standardkonforme
Möglichkeit an, dies zu bewerkstelligen. Würde eine solche Möglichkeit
bestehen, würde sie die Verletzung der const-Korrektheit ermöglichen!

Nicht ganz. Er will einen "vect<int*>&" als
"const vect<const int*>&" behandelen. Das ist meines Erachtens durchaus
const-korrekt.

Quote:
Ein analoges Problem gibt es übrigens mit Zeigerzeigern - da gestattet der Standard
aber ausdrücklich (siehe 4.4/4) die sicheren Umwandlungen:

int** ppi = 0;
int const** ppci = ppi; // Verboten
int const* const* pcpci = ppi; // Erlaubt

In Zeigerzeigern will er meines Erachtens genau die von Dir als
"Erlaubt" gekennzeichnete Variante. Folgendes ist alles erlaubt.

std::vector<int*> v1;
int** i=&v1[0];
const std::vector<const int*> v2;
int const* const* j1=i;
int const* const* j2=&v1[0];
int const* const* j3=&v2[0];


Helmut

--
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 Jun 18, 2004 10:37 pm    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote

Tobias Wollgam wrote:

Quote:
auch folgendes Problem hat mit constness zu tun:

void doSomething(const vector<int *>& v)
{
*v[0] = 0;
}

int main()
{
vector<int*> vi;
doSomething(vi);
return 0;
}

Ich möchte aber auch unterbinden, daß die Inhalte auf die die Pointer in v
zeigen geändert werden. Also:

void doSomething(const vector<const int *>& v)
{
*v[0] = 0; // nicht mehr erlaubt
}

Aber nun kann vi nicht mehr übergeben werden. Und den vector umzukopieren,
kann ja wohl nicht die Lösung sein! Übersehe ich da etwas oder ist das eine
Schwachstelle von C++?

Was spricht dagegen, statt des Containers die Iteratoren zu übergeben?

// vector mit const int => Zeiger dürfen geändert werden,
// nicht aber die Objekte dahinter
typedef std::vector<const int*> my_type;

void doSomething( my_type::iterator _begin, my_type::iterator _end )
{
*_begin = 0;
}

Für den nur-Lese Zugriff entsprechend der const_iterator. IMHO trennt
dir STL die Speicherung (Container) und Zugriff (Iterator) voneinander.
Daher sollte nicht der Container sondern der entsprechende Iterator
übergeben werden.

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
Tobias Wollgam
Guest





PostPosted: Sat Jun 19, 2004 8:53 am    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote

Markus Breuer wrote:

Quote:
Was spricht dagegen, statt des Containers die Iteratoren zu übergeben?

// vector mit const int => Zeiger dürfen geändert werden,
// nicht aber die Objekte dahinter
typedef std::vector<const int*> my_type;

void doSomething( my_type::iterator _begin, my_type::iterator _end )
{
*_begin = 0;
}

Für den nur-Lese Zugriff entsprechend der const_iterator. IMHO trennt
dir STL die Speicherung (Container) und Zugriff (Iterator) voneinander.
Daher sollte nicht der Container sondern der entsprechende Iterator
übergeben werden.

Die Idee ist prima, ich werd mal darüber nachdenken. Wenn die Lösung dann
auch nicht paßt, melde ich mich wieder :-)

--
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
Falk Tannhäuser
Guest





PostPosted: Sun Jun 20, 2004 2:57 pm    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote

Markus Breuer wrote:
Quote:
Tobias Wollgam wrote:
[snip]
int main()
{
vector<int*> vi;
doSomething(vi);
return 0;
}

Ich möchte aber auch unterbinden, daß die Inhalte auf die die Pointer
in v zeigen geändert werden. Also:

void doSomething(const vector<const int *>& v)
{
*v[0] = 0; // nicht mehr erlaubt
}

Aber nun kann vi nicht mehr übergeben werden.
[snip]

Was spricht dagegen, statt des Containers die Iteratoren zu übergeben?

// vector mit const int => Zeiger dürfen geändert werden,
// nicht aber die Objekte dahinter
typedef std::vector<const int*> my_type;

void doSomething( my_type::iterator _begin, my_type::iterator _end )
{
*_begin = 0;
}

Für den nur-Lese Zugriff entsprechend der const_iterator. IMHO trennt
dir STL die Speicherung (Container) und Zugriff (Iterator) voneinander.
Daher sollte nicht der Container sondern der entsprechende Iterator
übergeben werden.

Es gibt zwar für jeden Container jeden Inhalts die automatische Typumwandlung
von container<type>::iterator nach container<type>::const_iterator;
jedoch gibt es keine Umwandlung von container<type*>::iterator nach
container<type const*>::const_iterator, obwohl dies sicher (const-korrekt)
wäre und die analoge Typumwandlung von type** nach type const* const*
standardkonform ist.
So würde obiges doSomething, selbst mit my_type::const_iterator-Parametern,
keine Iteratoren in std::vector<int*> akzeptieren (es sei denn, die
Implementierung definiert die Iteratoren in std::vector als
typedef value_type* iterator;
typedef value_type const* const_iterator;
was z.B. bei Comeau <http://www.comeaucomputing.com/tryitout/> der Fall zu
sein scheint, aber nicht ausgenutzt werden darf, sofern der Kode portabel
sein soll!)

MfG
Falk
--
Die From-Adresse ist gültig, hat aber eine zeitlich beschränkte Lebensdauer.

--
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: Mon Jun 21, 2004 4:22 pm    Post subject: Re: const Problem mit Kontainern von Pointern Reply with quote

Falk Tannhäuser wrote:
Quote:
Markus Breuer wrote:

Für den nur-Lese Zugriff entsprechend der const_iterator. IMHO trennt
dir STL die Speicherung (Container) und Zugriff (Iterator)
voneinander. Daher sollte nicht der Container sondern der
entsprechende Iterator übergeben werden.


Es gibt zwar für jeden Container jeden Inhalts die automatische
Typumwandlung
von container<type>::iterator nach container<type>::const_iterator;
jedoch gibt es keine Umwandlung von container<type*>::iterator nach
container<type const*>::const_iterator, obwohl dies sicher (const-korrekt)
wäre und die analoge Typumwandlung von type** nach type const* const*
standardkonform ist.
So würde obiges doSomething, selbst mit my_type::const_iterator-Parametern,
keine Iteratoren in std::vector<int*> akzeptieren (es sei denn, die
Implementierung definiert die Iteratoren in std::vector als
typedef value_type* iterator;
typedef value_type const* const_iterator;
was z.B. bei Comeau <http://www.comeaucomputing.com/tryitout/> der Fall zu
sein scheint, aber nicht ausgenutzt werden darf, sofern der Kode portabel
sein soll!)

Ich will dir nicht widersprechen. Worauf ich hinaus will, ist eine
anders angedachte Verwendung von STL Containern. Die Container sind
nicht dazu konzipiert, per (const) Referenz/Pointer an Funktionen
übergeben zu werden, vielmehr soll mit den Iteratoren gearbeitet werden.
Das zeigen schon allein die Definitionen unter <algorithm> und
<iterator>.

Ursprünglich ging es um die Funktion

void doSomething(const vector<int *>& v)

die intern auf die Element direkt zugriff:

{
*v[0] = 0;
}

Möglicherweise ist es aber sinnvoller, ein Re-Design durchzuführen:

void doSomething( const int* _x);

Und den Aufruf via

std::for_each(
myVec.begin(),
myVec.end(),
doSomething
);

ausführen zu lassen. for_each soll jetzt nur exemplarisch sein, in
<algorithm> gibt es noch viel mehr Funktionen. Im Endeffekt geht man
dann anders mit den Daten um.

Beispiel:
Alle int's, die kleiner 0 sind, sollen auf 0 gesetzt werden.

void doSomething( vector<int *>& v )
{
for( ...::iterator it = myVec.begin(); it!=myVec.end(); ++it)
{
if ( **it < 0 )
**it = 0;
}
}

Könnte man auch so schreiben:

void if_lt_zero_set_value_to_zero( int* _value )
{
if ( *_value < 0 )
*_value = 0;
}

....
std::for_each(
myVec.begin(),
myVec.end(),
if_lt_zero_set_value_to_zero
);

Der Unterschied ist im wesentlichen, dass die Funktion sich nun um ein
einzelnes Element kümmert. Und hier kann wieder beliebig int* oder const
int* verwendest werden.

Durch diese Sichtweise habe ich ein besseres Verständnis für die STL
bekommen. Während der erste Ansatz eher prozedural ist (was mache ich),
ist der zweite Ansatz eher objekt-orientiert (mit welchem Element mache
ich es).
Wer sich einmal mit der Sprache Smalltalk auseinander gesetzt hat, wird
in den Algorithmen (insbesondere for_each) die Schnittstellen zu den
Smalltalk Collections wieder erkennen. Und diese waren u.a. Grundlage
für das STL Design.

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
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.