Das ist das Ende von C++!
-
quote experte schrieb:
...Ich versteh auch nicht, was du denn dauernd so zwangsweise kopieren willst, ...
Merke ich.
DAS ist der Kern meiner gesamten "primitive-Typen-Kritik": Weil primitive Typen IMMER kopiert werden, bräuchte man für eine Funktion, die dieselbe Semantik für primitive wie für Klassentypen besitzt (z.B. weil man sie als template schreiben will) eine "generalisierbare Kopiermöglichkeit für Klassentypen".Das bedeutet in keinster Weise, dass ich "(immer) kopieren will" ("kopieren sollte man dann, wenn man es braucht") .... sondern, dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Kopiersemantik zu übergeben.
Oder (besser beides): Dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Referenzsemantik zu übergeben (also auch für primitive Typen).
- zumindestens, wenn man templates konsistent einführen möchte.Gruß,
Simon2.
-
mdoemli schrieb:
...
ne by-reference wäre z.B. wenn du schreibstint a = 3;
int b = 4;int switch(&a, &b);
...Und dafür gilt das Folgende nicht ?
mdoemli schrieb:
ok erstens man übergibt kein objekt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
sondern einen zeiger!!!!!!!!!!!!!!objekt x zeigt auf speicher-adresse 0xf321 (= value)
so nun zeigt a auch auf 0xf321 (=value). aber a ist by-value, d.h. nach
beendigung der funktion ist a nicht mehr da!!!!!!!!!!
aber value schon!!!!!!!!!!!!!!!!!!!!wenn du nun a.value = 3;
x.value auch 3
gruß mdoemli
Da übergibst Du doch auch nur "ein 0xf0321" ....
Gruß,
Simon2.
-
Ich finde es sollte auch nicht anhand von so syntaktischen Kleinigkeiten wie ob ein */& oder eben nix dasteht, abhängig sein sollte.
// C++ void foo(Bar* baz) { baz = new Bar; } // baz bleibt beim Aufrufer vor und nach der Funktion gleich -> Call-By-Value void foo(Bar& baz) { baz = new Bar; // ich weiß das wohl syntaktisch nicht korrekt ist } // baz ist nach dem Funktionsaufruf verändert
Egal wie man es dreht oder wendet im 2. Fall arbeitet man immer mit dem Original. Die Übergabe eines Zeigers als Call-By-Reference zu erklären, halt ich für falsch. Dann müsste ja folgender Typ auch ein "reiner Referenzdatentyp" sein.
class Foo { private: Bar* bar = new Bar; public: void bla() { bar->moo(); } }
Auch hier kannst du soviel "kopieren", wie du willst, du arbeitest im Wesentlichen eigentlich immer mit der selben Instanz (hängt jetzt natürlich davon ab, wie man die Identität definiert.)
-
Das bedeutet in keinster Weise, dass ich "(immer) kopieren will" ("kopieren sollte man dann, wenn man es braucht") .... sondern, dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Kopiersemantik zu übergeben.
Um dir das anders zu verdeutlichen: Durchsuch einfach mal Open-Source Java Projekte (beispielsweise von der Apache Foundation) und such nach dem Methodenaufruf clone() um zu erfahren, wie sehr man Kopien in der Java Entwicklung benötigt. Um dir etwas Arbeit abzunehmen habe ich einfach mal Apache Shale hergenommen und rate mal auf wieviele Treffer ich gekommen bin. 0. Wie gesagt, du bildest dir die Probleme einfach nur ein.
Oder (besser beides): Dass ich für alle Typen die Möglichkeit haben möchte, sie mit der Referenzsemantik zu übergeben (also auch für primitive Typen). - zumindestens, wenn man templates konsistent einführen möchte.
"Referenzsemantik" wird doch sowieso für primitive Datentypen auch geboten, du musst ja nur die Wrapper verwenden. Wo ist denn bei Generics eine Inkonsistenz? Schreib doch einfach Integer statt int, musst es ja nur bei der Deklaration machen und es wurden dadurch weder Kompatibiltäten gebrochen noch Komplexitäten geschaffen. Wenn du diese Lösung nicht akzeptieren willst, kannst du ja gleich auch argumentieren "Aber Java ist nicht C++, deshalb ist Java schlecht .." ...
-
Jester schrieb:
doch, die adresse wird kopiert. Und das ist die Stelle wo man sich nun streiten kann: Wird in Java die Referenz by value übergeben, oder das referenzierte Objekte by reference?
Mein Argument ist folgendes: Man kann in Java Objekte überhaupt nicht direkt anfassen, sondern immer nur per Referenz. Man arbeitet immer nur durch die Referenz mit dem Objekt. Egal, ob man die Referenz jetzt einer Funktion übergibt oder zurückgibt oder einer Variablen zuweist. Ich finde diese Sichtweise logisch und systematisch sehr sauber. Man findet sowas auch in anderen Sprachen, ich sag jetzt nur mal Lisp, wo alles by-value übergeben wird, auch wenn es sich bei den Werten in den meisten Fällen um verkappte Zeiger handelt.
.NET geht dann übrigens noch einen Schritt weiter und erlaubt tatsächlich die Übergabe von (u.a.) Objektreferenzen by-reference. Wie will man sowas verstehen, wenn man sich mit Sonderfallunterscheidungen zwischen primitiven und Klassentypen, die im Grunde künstlich und sinnlos sind, herumschlägt?Irgendwer hatte auch die Zeigerübergabe in C als Beispiel angesprochen. Das ist relativ einfach IMHO, man simuliert dadurch eine Übergabe by-reference, aber man macht eine Übergabe by-value.
Die Referenztypen von C++ sind die echte Schwierigkeit.
-
Zeus schrieb:
Optimizer schrieb:
In C# würde es T oder ref T heißen.
In C# muss du nur Werttype als ref übergeben, sonst auch nicht.
Das stimmt so nicht. Wenn du Ref bei Wertetypen anwendest wird die Referenz übergeben. Wenn du Ref bei Referenztypen anwendest wird die Referenz auf die Referenz übergeben, so das du die Referenz ändern kannst.
-
Mein Trollbeitrag hat jetzt schon 21 Seiten
-
Zwergli schrieb:
Zeus schrieb:
Optimizer schrieb:
In C# würde es T oder ref T heißen.
In C# muss du nur Werttype als ref übergeben, sonst auch nicht.
Das stimmt so nicht. Wenn du Ref bei Wertetypen anwendest wird die Referenz übergeben. Wenn du Ref bei Referenztypen anwendest wird die Referenz auf die Referenz übergeben, so das du die Referenz ändern kannst.
ops wieder dazugelernt
-
quote experte schrieb:
...und such nach dem Methodenaufruf clone() um zu erfahren, wie sehr man Kopien in der Java Entwicklung benötigt. ...
Sorry, aber Du willst es nicht verstehen, oder ?
Hat es eigentlich noch einen Zweck, es zu versuchen ? Welche Sprache soll ich nehmen ? Kennst Du den Unterschied zwischen Strukturellem ubd Konkretem ? ....Vielleicht ist mein Source schon zu weit weg, deswegen nochmal:
Wenn ich (ALS TEMPLATE-PROGRAMMIERER !!!) etwas schreiben will wie ("Kopiersemantik"):template <typename T> void f(T); int main(void) { int i; myClass s; f<int>(i); f<myClass>(s); // (1) geht in Java nicht; oder eben nur mit manuellem cloning ...
=> f() arbeitet auf einer Kopie, egal, für welchen Typ ich ihn instantiiere.
Wenn ich alternativ Folgendes schreiben will ("Referenzsemantik"):
template <typename T> void f(T&); int main(void) { int i; myClass s; f<int>(i); // (2) geht in Java nicht; oder eben nur mit "Hin-/Her-Wrapperei" beim Aufruf f<myClass>(s); // BTW ich weiß, wo mir ADL die <..> abnehmen würde; dient hier der Verdeutlichung
=> f() arbeitet auf dem Original, egal, für welchen Typ ich ihn instantiiere.
Will ich dasselbe Verhalten haben, brauche ich in beiden Fällen unterscheidliche templates für primitive Typen und für Klassentypen.
- Entweder (Kopier) muss ich bei (1): In f<myClass>() oder bei jedem Aufruf clonen;
- Oder (Referenz) ich muss bei jedem Aufruf von f<int>() vorher in Integer wrappen und den Wert wieder zurück in meinen int übertragen (wenn es denn wirklich ein int sein soll) .... aber:
quote experte schrieb:
...
"Referenzsemantik" wird doch sowieso für primitive Datentypen auch geboten, du musst ja nur die Wrapper verwenden. ... Schreib doch einfach Integer statt int, musst es ja nur bei der Deklaration machen und es wurden dadurch weder Kompatibiltäten gebrochen noch Komplexitäten geschaffen. ...Einen besseren Beleg für meine These konntest Du kaum bringen:
Das bedeutet, dass ich primitive Typen nicht im Zusammenhang mit templates nutzen sollte - mehr habe ich nicht behauptet.Ich glaube, deutlicher kann ich es wirklich nicht mehr ausdrücken. Wenn Du mit jetzt vorschlägst, "i"s mittels Search&Replace in Word durch "I"s zu ersetzen, weiß ich Bescheid, dass ich mir die Mühe schon länger hätte sparen können.
Gruß,
Simon2.
P.S.: Im Übrigen geht es mir immer noch nicht darum, Java oder deren Generics schlechtzureden ... ich unterbreite nur einen Vorschlag, wie IMO in einer zukünftigen Sprache "Unschönheiten" ausgebügelt werden können ... dass das für Javas (nachgeschobene) Generics nicht mehr geht, ist mir auch klar - ebensowenig, wie einige grundlegende Unschönheiten in C++ ausgebügelt werden können.
-
Bashar schrieb:
...Wie will man sowas verstehen, wenn man sich mit Sonderfallunterscheidungen zwischen primitiven und Klassentypen, die im Grunde künstlich und sinnlos sind, herumschlägt?....
Sehr gut ... genauergesagt: Nur wenn man das versteht, merkt man, wie künstlich und sinnlos diese Sonderfallunterscheidungen sind .... und nur deswegen plädiere ich ja für die Aufhebung dieser Sonderrolle der primitiven Typen (s. mein erstes Post).
Gruß,
Simon2.
-
Jester schrieb:
mdoemli schrieb:
mhh, ok.
aber bei call-by-ref wird eben nichts kopiert. das ist ja der unterschied.doch, die adresse wird kopiert. Und das ist die Stelle wo man sich nun streiten kann: Wird in Java die Referenz by value übergeben, oder das referenzierte Objekte by reference?
Die Referenz by value, sonst würde sowas gehen
public void abc(List list) { list = new LinkedList(); } ... List list = null; abc(list); list.add(new File("c:\\");
-
Wie kann man eigentlich in D ein Objekt erstellen, dass nach der Initialisierung, welche laufzeitabhängig ist, nicht mehr verändert werden darf? Also was in C++ mittels const gemacht wird. Soweit ich das verstanden habe, ist das const in D nur für compile-time Konstanten verwendbar?
Und wofür sind eigentlich diese Mixins in D nützlich? Werde aus den Beispilen nicht so richtig schlau.
-
Bashar schrieb:
Jester schrieb:
doch, die adresse wird kopiert. Und das ist die Stelle wo man sich nun streiten kann: Wird in Java die Referenz by value übergeben, oder das referenzierte Objekte by reference?
Mein Argument ist folgendes: Man kann in Java Objekte überhaupt nicht direkt anfassen, sondern immer nur per Referenz. Man arbeitet immer nur durch die Referenz mit dem Objekt. Egal, ob man die Referenz jetzt einer Funktion übergibt oder zurückgibt oder einer Variablen zuweist. Ich finde diese Sichtweise logisch und systematisch sehr sauber. Man findet sowas auch in anderen Sprachen, ich sag jetzt nur mal Lisp, wo alles by-value übergeben wird, auch wenn es sich bei den Werten in den meisten Fällen um verkappte Zeiger handelt.
.NET geht dann übrigens noch einen Schritt weiter und erlaubt tatsächlich die Übergabe von (u.a.) Objektreferenzen by-reference. Wie will man sowas verstehen, wenn man sich mit Sonderfallunterscheidungen zwischen primitiven und Klassentypen, die im Grunde künstlich und sinnlos sind, herumschlägt?Irgendwer hatte auch die Zeigerübergabe in C als Beispiel angesprochen. Das ist relativ einfach IMHO, man simuliert dadurch eine Übergabe by-reference, aber man macht eine Übergabe by-value.
Die Referenztypen von C++ sind die echte Schwierigkeit.
Bashar's Sichtweise teile ich voll und ganz. Ich habe auch immer so argumentiert, dass man zwar einen Zeiger gibt, den aber by value. Kann man leicht nachprüfen, indem man versucht, den Zeiger für den Aufrufer zu verbiegen - geht nicht. Man kann natürlich so denken, dass man ein Objekt übergibt und das by ref, aber völlig den Tatsachen entspricht das nicht, spätestens wenn man null übergibt widerspricht man sich irgendwie selbst. "Ich übergebe nichts, veränderbar"
Zwergli schrieb:
Zeus schrieb:
Optimizer schrieb:
In C# würde es T oder ref T heißen.
In C# muss du nur Werttype als ref übergeben, sonst auch nicht.
Das stimmt so nicht. Wenn du Ref bei Wertetypen anwendest wird die Referenz übergeben. Wenn du Ref bei Referenztypen anwendest wird die Referenz auf die Referenz übergeben, so das du die Referenz ändern kannst.
Genau.
Simon2 schrieb:
Bashar schrieb:
...Wie will man sowas verstehen, wenn man sich mit Sonderfallunterscheidungen zwischen primitiven und Klassentypen, die im Grunde künstlich und sinnlos sind, herumschlägt?....
Sehr gut ... genauergesagt: Nur wenn man das versteht, merkt man, wie künstlich und sinnlos diese Sonderfallunterscheidungen sind .... und nur deswegen plädiere ich ja für die Aufhebung dieser Sonderrolle der primitiven Typen (s. mein erstes Post).
Gruß,
Simon2.
Ich denke aber du verstehst es nicht völlig so, wie es gemeint ist. Du kritisiertest dass die primitiven Typen als Parameter eine Sonderrolle in Java hätten, haben sie aber nicht. Es gibt als Parameter nur primitive Typen oder Referenzen, beide werden kopiert. Es werden nicht Objekte übergeben. Zu denken, dass man Objekte übergibt und die dann by ref, führt erst diese sinnlose Unterscheidung ein.
-
Simon2 schrieb:
Bashar schrieb:
...Wie will man sowas verstehen, wenn man sich mit Sonderfallunterscheidungen zwischen primitiven und Klassentypen, die im Grunde künstlich und sinnlos sind, herumschlägt?....
Sehr gut ... genauergesagt: Nur wenn man das versteht, merkt man, wie künstlich und sinnlos diese Sonderfallunterscheidungen sind .... und nur deswegen plädiere ich ja für die Aufhebung dieser Sonderrolle der primitiven Typen (s. mein erstes Post).
Versteh ich nicht. Die Fallunterscheidung passiert ja im Kopf des Benutzers, man muss die Sprache dafür nicht ändern, die macht von vornherein keinen Unterschied.
-
groovemaster schrieb:
Wie kann man eigentlich in D ein Objekt erstellen, dass nach der Initialisierung, welche laufzeitabhängig ist, nicht mehr verändert werden darf? Also was in C++ mittels const gemacht wird. Soweit ich das verstanden habe, ist das const in D nur für compile-time Konstanten verwendbar?
Nein leider gibt es in D keine solchen Einmal-Zugriffs-Konstanten. Allerdings frage ich mich, wann es eine sinnvolle Anwendung einer solchen gäbe und ob es dann nicht eine bessere Lösung geben könnte.
Und wofür sind eigentlich diese Mixins in D nützlich? Werde aus den Beispilen nicht so richtig schlau.
Ja die Beispiele in der D-Spec sind nicht immer ganz durchsichtig bzw. muss man teils auf die Details achten. Mixins ergänzen das relativ mächtige template system in D.
man kann z.B. so etwas machen (um Code abzukürzen bzw. Modularisierung):template A(int i) { int b = i; } int main() { mixin A!(9); return b; }
Ist jetzt recht sinnlos, aber vielleicht zeigts irgendwas besser?
Sonst gibts es noch ein Beispiel für die Anwendung eines Mixins, nämlich das std.signals Modul: Ein Signal wird nicht durch Vererbung gemacht, sondern so:class SignalGeber { mixin Signal!(int, char[] /* Typen */) signal; }
Also für mich sind Mixins nur eine Möglichkeit, Code eventuell lesbarer/kürzer zu halten und sich Schreib- und Wartungsarbeit zu ersparen.
-
Zwergli schrieb:
Zeus schrieb:
Optimizer schrieb:
In C# würde es T oder ref T heißen.
In C# muss du nur Werttype als ref übergeben, sonst auch nicht.
Das stimmt so nicht. Wenn du Ref bei Wertetypen anwendest wird die Referenz übergeben. Wenn du Ref bei Referenztypen anwendest wird die Referenz auf die Referenz übergeben, so das du die Referenz ändern kannst.
Eigentlich ging es mir auch mehr um diese verhalten
using System; using System.Collections.Generic; namespace aref { class test { public int i;} struct test2 { public int i;} class MainClass { public static void change(test t){ t.i = 2; } public static void change2(ref test2 t){ t.i = 2; } public static void Main(string[] args){ test t = new test(); test2 t2 = new test2(); change(t); change2(ref t2); Console.WriteLine(t.i); Console.WriteLine(t2.i); Console.ReadLine(); } } }
-
Vielleicht ist mein Source schon zu weit weg, deswegen nochmal:
Wenn ich (ALS TEMPLATE-PROGRAMMIERER !!!) etwas schreiben will wie ("Kopiersemantik"):Ich glaube eher, dass du es nicht kapieren willst, denn auch in C++ lassen sich nicht zwangsweise alle Objekte kopieren. Die Sache mit dem generischen Ansatz in Templates kannst du also ohnehin vergessen, da auch in C++ Fallunterscheidungen zu treffen sind.
f<myClass>(s); // (1) geht in Java nicht; oder eben nur mit manuellem cloning
Wie bereits gesagt wär das ja auch noch schöner, wenn man schlichtweg alles kopieren könnte. Jedes Singleton ist für die Katz, sämtliche globalen Policies lassen sich (unabsichtlich) verfälschen, etc.. und das ist es was du wohl nicht kapieren willst. Es ist ein Fehler anzunehmen, dass der Autor einer Funktion oder Methode darüber entscheidet, wie Parameter übergeben wird, denn das kann er nicht so objektiv entscheiden, wie die Entwickler der einzelnen Parameter-Typen. Insofern ist es mehr als nur konsequent und sauber zu sagen, dass du unterschiedliche Typen für unterschiedliche Semantiken zu verwenden hast (einfachstes Beispiel: int und Integer).
Kennst Du den Unterschied zwischen Strukturellem ubd Konkretem ? ....
Wenn du dich auf derartige Rechtfertigungen beziehst, kann man ja daraus schließen, dass C++ für theoretische Probleme und Java für praktische Probleme geeignet ist. Ich frag mich da nur, welche in der Praxis häufiger auftreten (und besser bezahlt werden) ...
-
Will nichts zu den zahllosen Einzeldiskussionen beitragen, aber ich wäre für ein D-Unterforum; Einfach der Vollständigkeit halber und damit man eine Anlaufstelle hat, falls man es mal ausprobieren möchte
-
Badestrand schrieb:
Will nichts zu den zahllosen Einzeldiskussionen beitragen, aber ich wäre für ein D-Unterforum; Einfach der Vollständigkeit halber und damit man eine Anlaufstelle hat, falls man es mal ausprobieren möchte
Neue Unterforen werden erst bei Bedarf erstellt.
-
lol, Simon2, warum überlässt du probleme der informatik nicht den informatikern undgehst wieder an deinen computer und programmierst brav weiter...