🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: de.comp.lang.c++
Article #1607

Re: Verwendung von char* in C++ (War: Q: gcc 2.7.1: Aufruf einer Konstruktormethode...)

#1607
From: Dietmar Kuehl
Date: Thu, 22 Feb 1996 18:13
126 lines
5465 bytes
Hi,

abgesehen davon, dass die Klasse ziemlich albern ist (aber ich hab es
ja gradezu provoziert), gibt es dazu trotzdem eine kleine (nicht
persoenliche) Anmerkung:

Watson (sayegh@fokus.gmd.de) wrote:

: class charPointer {
:     char *value;
:     public:
:     charPointer(char *aValue) {
:         value = aValue;
:     }

Bei einem einfachen Member, wie 'char*' macht es vermutlich, ob des
Optimierers, keinen echten Unterschied, aber bei komplizierteren Membern
sollte man auf jeden Fall eine 'mem-initializer-list' verwenden, also
den Konstruktor folgendermassen schreiben:

      charPointer(char *aValue):
	value(aValue)
      {
      }

Das verhindert, dass der Member erst konstruiert wird (mit dem
Default-Konstruktor, den es oft genug ohnehin nicht gibt, so dass das
sowieso nicht geht) und dann gleich wieder mit einem neuen Wert (per
Assignment-Operator) ueberschrieben wird. Stattdessen wird direkt eine
Kopie des Arguments mittels Copy-Konstruktor angelegt. Diese Methode
funktioniert nur in dem eher seltenen Fall nicht, dass es keinen
Copy-Konstruktor gibt. Dann ist aber auch unwahrscheinlich, dass es
eine Default-Konstruktor UND einen Assignment-Operator gibt (denn dann
koennte man ja den Copy-Konstruktor so implementieren wie den
Default-Konstruktor mit einem nachgeschalteten Assignment).

... und gleich noch was relativ neues aus dem Standard: Fuer den Fall,
dass man eine etwaige Exception bei der Konstruktion eines Members in
der 'mem-initializer-list' abfangen will, kann man das so schreiben:

      charPointer(char *aValue)
	try
	{
	  : value(a_value)
	  {
	  }
	}
	catch (...)
	{
	}

Das geht aber nur fuer Konstruktoren (und ich bin mir nicht sicher, ob
der ':' vor oder nach dem 'try' hingehoert...).

:     operator char*() {
:         return value;
:     }
:     charPointer& operator =(char* aValue) {
:         value = aValue;
:         return *this;
:     }
:     char& operator[](int i) {
:         return value[i];
:     }
: };

: Keine ueble Sache, was ;-)?

Schliesslich, hier ein Template, dass man in den passenden Faellen als
"Smarter Pointer" (smart ist es naemlich nicht...) benutzen kann (ich
meine das durchaus ernst):

  template <class T>
  class UnmanagedPointer
  {
  private:
    T *i_res;
  public:
    explicit UnmanagedPointer(T *res = 0): i_res(res) {}
    // The generated copy ctor, assignment, and dtor are suitable

    T    *operator-> () const      { return i_res; }
    T    &operator[] (int i) const { return i_res[i]; }
    T    &operator* () const       { return *i_res; }
    T    *get() const              { return i_res; }
    T    *release()                { T *rc = i_res; i_res = 0; return rc; }
    void reset(T* res = 0)         { i_res = res; }
  };

Abgesehen davon, dass durch die Klasse (im Code) deutlich gemacht wird,
dass man sich um den Pointer nicht zu kuemmern braucht, kann man einen
'UnmanagedPointer' ueberall dort verwenden, wo man einen 'auto_ptr'
oder eine vergleichbare Klasse verwenden kann (sofern die Polymorphie
mittels Templates und nicht mittels Vererbung gemacht wird).  Daneben
hat diese Klasse, etwa gegenueber einem 'raw pointer' (und der Klasse
'charPointer') noch den Vorteil, dass sie nicht an der 'integral
promotion' teilnimmt, man kann also z.B. nicht "aus Versehen" schreiben

  f(UnmanagedPointer<char> &ptr)
  {
    if (ptr) // geht nicht
      ...
  }

sondern muss schon entweder '*ptr' oder 'ptr->get()' (je nachdem ob man
anhand des Wertes oder des Zeigers entscheiden will) schreiben. Auch
das Vermeiden von impliziten Konversion ist vermutlich ein Aspekt, den
viele nur als vermeintlichen Vorteil sehen werden. Aber immerhin hat es
das Standardisierungs-Kommittee fuer noetig befunden, 'explicit'
einzufuehren, damit man bestimmte Konversion verhindern kann bzw. man
muss die Konversion eben explizit fordern (durch einen passenden
Konstruktoraufruf).

Aber nichts fuer ungut. Vielleicht schafft ihr es ja doch noch
irgendwann mich zu ueberzeugen. Allerdings denke ich derzeit, dass es
besser waere, ihr wuerdet euch ueberzeugen lassen (klar, sonst waere
ich ja dumm, mich nicht von euch ueberzeugen zu lassen...). ... und
fuer den Fall, dass ich anfange der Meinung zu sein, dass frei
rumfliegende Pointer 'ne tolle Sache sind, brauche ich wohl nur mal
kurz mit James Kanze (man gucke sich einfach sein Artikel zum Thema
'auto_ptr' etc. an) darueber zu diskutieren, dann ist der Anfall wohl
wieder vorbei :-)
--
dietmar.kuehl@uni-konstanz.de
http://www.informatik.uni-konstanz.de/~kuehl
I am a realistic optimist - that's why I appear to be slightly pessimistic
Technical Details
Message-ID: <4gibof$1qa@news.BelWue.DE>
Path: arc1-ca.pugleaf.net!news.belwue.de!uzwil!kuehl
References: <3120B25C.2650@fokus.gmd.de> <31229576.0@news.uni-konstanz.de> <pu91i3yvzc.fsf@themroc.colibri.de> <BOP9B96C@wuschel.ibb.schwaben.com> <4gdb6p$i5j@news.BelWue.DE> <W7Q9BM6M@wuschel.ibb.schwaben.com> <4ggkbr$7vr@news.BelWue.DE> <312C5E01.1435@fokus.gmd.de>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!news.belwue.de!uzwil!kuehl
From: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl)
Newsgroups: de.comp.lang.c++
Subject: Re: Verwendung von char* in C++ (War: Q: gcc 2.7.1: Aufruf einer Konstruktormethode...)
Date: 22 Feb 1996 18:13:35 GMT
Organization: Fakultät für Mathematik und Informatik
Message-ID: <4gibof$1qa@news.BelWue.DE>
References: <3120B25C.2650@fokus.gmd.de> <31229576.0@news.uni-konstanz.de> <pu91i3yvzc.fsf@themroc.colibri.de> <BOP9B96C@wuschel.ibb.schwaben.com> <4gdb6p$i5j@news.BelWue.DE> <W7Q9BM6M@wuschel.ibb.schwaben.com> <4ggkbr$7vr@news.BelWue.DE> <312C5E01.1435@fokus.gmd.de>
Reply-To: dietmar.kuehl@uni-konstanz.de
NNTP-Posting-Host: uzwil.informatik.uni-konstanz.de
X-Newsreader: TIN [version 1.2 PL2]