Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Warum sind Zuweisungen in C++ lvalues?

0 views
Skip to first unread message

Lars Rohwedder

unread,
Jun 22, 2008, 10:42:00 AM6/22/08
to
Anders als in C, wo das Ergebnis einer Zuweisung ein rvalue ist, ist es
in C++ ein lvalue. ([5.17])

Damit wird folgender Code syntaktisch(!) legal, auch wenn das Ergebnis
natürlich "undefined" ist, da auf x zweimal geschrieben wird, ohne dass
ein Sequence point zwischen den Schreibzugriffen liegt:

(x=3)=4;

Ich frage mich, wieso man in C++ aus Zuweisungen lvalues gemacht hat.
Gibt es irgendeinen sinnvollen Grund dafür und/oder ein
Anwendungsbeispiel, welches diese Änderung ausnutzt und kein "undefined
behavior" besitzt?

Gruß,
Lars R.

Message has been deleted

Lars Rohwedder

unread,
Jun 22, 2008, 2:16:17 PM6/22/08
to
Stefan Ram <r...@zedat.fu-berlin.de> wrote:

> Lars Rohwedder <l...@spamt.net> writes:
>>Ich frage mich, wieso man in C++ aus Zuweisungen lvalues gemacht hat.
>
> Siehe auch »222. Sequence points and lvalue-returning operators« in
>
> http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html

Da wird auch über den Unsinn dieser Festlegung und die Probleme, die
man sich damit einhandelt. Ich habe kein Posting gefunden, dass die
Gründe oder Vorteile erläutert.

L.

Stefan Reuther

unread,
Jun 22, 2008, 4:44:00 PM6/22/08
to
Lars Rohwedder wrote:
> Ich frage mich, wieso man in C++ aus Zuweisungen lvalues gemacht hat.
> Gibt es irgendeinen sinnvollen Grund dafür und/oder ein
> Anwendungsbeispiel, welches diese Änderung ausnutzt und kein "undefined
> behavior" besitzt?

Zum Beispiel
void increment(int& i) { ++i; }
int a;
void foo() {
increment(a = 2);
}
So wie's dasteht ist das jetzt nicht unbedingt besonders hübsch, und
stilistisch auch tendenziell eher zu vermeiden, aber sicherlich gibt es
wesentlich sinnvollere Anwendungsbeispiele dieses Musters.


Stefan

James Kanze

unread,
Jun 23, 2008, 4:02:56 AM6/23/08
to
On Jun 22, 4:42 pm, Lars Rohwedder <l...@spamt.net> wrote:
> Anders als in C, wo das Ergebnis einer Zuweisung ein rvalue ist, ist es
> in C++ ein lvalue. ([5.17])

> Damit wird folgender Code syntaktisch(!) legal, auch wenn das Ergebnis
> natürlich "undefined" ist, da auf x zweimal geschrieben wird, ohne dass
> ein Sequence point zwischen den Schreibzugriffen liegt:

> (x=3)=4;

Wenn x einen benutzerdefinierten Typ hat, ist das Verhalten
nicht undefiniert.

> Ich frage mich, wieso man in C++ aus Zuweisungen lvalues gemacht hat.
> Gibt es irgendeinen sinnvollen Grund dafür und/oder ein
> Anwendungsbeispiel, welches diese Änderung ausnutzt und kein "undefined
> behavior" besitzt?

Die einfache Antwort ist: weil man kann. In C++ ist alles
lvalue, dessen Wert ein Objekt entspricht. Typischerweise wird
es beim Rückgaben von Referenzen benutzt, so ungefähr:

int const&
Klasse::f()
{
return wert = 2 ;
}

(Ob es gut ist, solchen Code zu schreiben, ist eine andere
Frage.)

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thomas Richter

unread,
Jun 23, 2008, 2:36:50 AM6/23/08
to
Lars Rohwedder schrieb:

Die "offizielle" Begründung, die Andrew Koenig dazu liefert, sagt etwa
folgendes:

Bei einer Methode, die Werte zurückliefert, sind die folgenden beiden
Statements äquivalent:

x=y;
return x;

und

return x=y;

Liefert diese Methode jetzt statt Werte Referenzen zurück, so wäre bei
direkter Übernahme der C-Semantik letzeres ein r-Wert, obiges aber ein
l-Wert, und damit die Äquivalenz nicht mehr gegeben.

Ergänzung meinerseits: Denke etwa an Fälle, bei denen Du wirklich große
Objekte an Methoden übergibtst (etwa: eine 100x100 Matrix).
Natürlicherweise würde man so etwas mit dem "mad-CoW"-Idiom lösen, d.h.
statt Werte Referenzen übergeben, und erst bei Zuweisung oder Änderung
des Objektes eine Kopie anlegen. Funktionen, die auf solchen Objekten
arbeiten nehmen dann natürlicherweise eine Referenz auf Objekte (und
nicht das Objekt selbst) als Argument. In derartigen Fällen würde etwa
ein Aufruf wie

det(prod = a*b)

wobei a und b Matrizen und det() eine Methode auf Matrizen (etwa die
Determinante) ist, zunächst einen r-Wert erhalten, der dann kopiert
werden müsste, um an det() übergeben werden zu können. Ist das Resultat
ein l-Wert, kann man diese Kopie sparen und det direkt Referenzen (statt
Objekte) als Argumente nehmen lassen.

Anmerkung ist, dass ich auch dieses Argument nicht für recht zugkräftig
halte. Man könnte einerseits sagen, dass dies eine Frage einer passenden
Compileroptimierung sein solle (wie man dies in C++ oft sagt), oder, da
det() offenbar eine const Matrix & benötigt, das Resultat einer
Zuweisung auf einen const-lvalue einschränken, was einige der offenbar
"gefährlichen" Konstruktionen wie (a=b)=c verhindern würde. (Ich finde
diese Syntax extrem unintuitiv und gefährlich, vielleicht mag mich
jemand vom Gegenteil überzeugen.)

Grüße,
Thomas

0 new messages