C ++ - Funktionen für das gesamte Team?

16

In C ++ wirken sich Funktionen wie Ausnahmen auf das gesamte Programm aus: Sie können sie entweder in Ihrem gesamten Programm deaktivieren oder Sie müssen sie im gesamten Code behandeln. Wie ein berühmter Artikel in C ++ Report es ausdrückt:

Gegenintuitiv ist der schwierige Teil der Codierung von Ausnahmen nicht das explizite Werfen und Fangen. Der wirklich schwierige Teil der Verwendung von Ausnahmen besteht darin, den gesamten dazwischenliegenden Code so zu schreiben, dass sich eine beliebige Ausnahme von ihrer Throw-Site zu ihrem Handler ausbreiten kann, ohne dabei andere Teile des Programms zu beschädigen.

Da sogar newAusnahmen ausgelöst werden, muss jede Funktion grundlegende Ausnahmesicherheit bieten - es sei denn, sie ruft nur Funktionen auf, die garantieren, dass keine Ausnahmen ausgelöst werden -, es sei denn, Sie deaktivieren die Ausnahmen im gesamten Projekt .

Ausnahmen sind daher ein "Gesamtprogramm" - oder "Gesamtteam" -Feature, da sie von jedem in einem Team, das sie verwendet, verstanden werden müssen. Aber meines Wissens sind nicht alle C ++ - Funktionen so.

Ein mögliches Beispiel ist, dass ich, wenn ich keine Vorlagen erhalte, diese aber nicht verwende, immer noch in der Lage sein werde, korrektes C ++ zu schreiben - oder nicht? Ich kann sogar sorteine Reihe von ganzen Zahlen aufrufen und deren erstaunlichen Geschwindigkeitsvorteil genießen. C's qsort(weil kein Funktionszeiger aufgerufen wird), ohne Fehler zu riskieren - oder nicht? Es scheint, dass Templates nicht das ganze Team sind.

Gibt es andere C ++ - Funktionen, die sich auf den Code auswirken, wenn sie nicht direkt verwendet werden, und sind sie daher "ganzes Team"? Ich interessiere mich besonders für Features, die in C nicht vorhanden sind.

Update : Ich bin besonders auf der Suche nach Funktionen, bei denen es kein sprachgesteuertes Zeichen gibt, auf das Sie achten müssen. Die erste Antwort, die ich erhielt, war die Konstanz, die auch das ganze Team betrifft. Daher muss jeder etwas darüber lernen. AFAICS hat jedoch nur dann Auswirkungen auf Sie, wenn Sie eine Funktion aufrufen, die als markiert gekennzeichnet ist const, und der Compiler verhindert, dass Sie sie für Nicht-Const-Objekte aufrufen, sodass Sie etwas zum googeln erhalten. Mit Ausnahmen bekommt man das nicht einmal; Darüber hinaus werden sie immer verwendet, sobald Sie sie verwenden new. Daher sind Ausnahmen "heimtückischer". Da ich dies jedoch nicht objektiv formulieren kann, werde ich jedes Feature für das gesamte Team zu schätzen wissen.

Update 2 : Anstelle der C ++ - Funktion hätte ich so etwas wie "C ++ - spezifisches Feature" schreiben sollen, um Dinge wie Multithreading auszuschließen, die für eine große Anzahl gängiger Programmiersprachen gelten.

Anhang: Warum ist diese Frage objektiv (wenn Sie sich fragen)

C ++ ist eine komplexe Sprache, daher versuchen viele Projekte oder Codierungshandbücher, "einfache" C ++ - Features auszuwählen, und viele Leute versuchen, einige nach meist subjektiven Kriterien einzuschließen oder auszuschließen. Fragen dazu werden hier auf SO regelmäßig zu Recht geklärt.

Oben habe ich stattdessen (so genau wie möglich) definiert, was ein "Ganzteam" -Sprachenfeature ist, ein Beispiel (Ausnahmen) zusammen mit umfangreichen Belegen in der Literatur zu C ++ angegeben und nach Ganzteamfeatures in C ++ gefragt über Ausnahmen hinaus.

Ob Sie "Ganzteam" -Funktionen verwenden sollten oder ob dies ein relevantes Konzept ist, mag subjektiv sein - aber das bedeutet nur, dass die Wichtigkeit dieser Frage wie immer subjektiv ist.

Blaisorblade
quelle

Antworten:

11

Ich würde Parallelität als "Ganzes Team" -Feature vorschlagen.

Obwohl es möglich ist, die Software so zu gestalten, dass nur wenige Experten sich der Parallelitätsproblematik bewusst sind und der Rest des Teams die Vorteile nutzen kann, ohne sich um die Komplexität zu kümmern (wie Sie es mit Vorlagen tun können), ist dies in der Praxis der Fall nicht so arbeiten. Wenn Sie in der Praxis mehrere Threads haben, müssen Sie sorgfältig für jede von Ihnen verwendete Variable analysieren, ob bei dieser Verwendung potenzielle Parallelitätsprobleme auftreten.

Bart van Ingen Schenau
quelle
Ich bin damit einverstanden, dass Threads solche Features für das gesamte Team sind, obwohl sie nicht C ++ - spezifisch sind. Es gibt jedoch auch andere Schnittstellen zur Parallelität (nicht threadbasiert), meistens in anderen Sprachen, und einige erlauben eine bessere Verkapselung der Parallelität (obwohl dies immer noch ein aktuelles Forschungsthema in Programmiersprachen ist). Es ist also eine offene Frage, ob dies für die Parallelität per se gilt.
Blaisorblade
@Blaisorblade - C ++ 11 hat eine eigene Threading-Bibliothek eingeführt, also ist es jetzt Teil von C ++.
Michael Kohne
@MichaelKohne: Ich habe nicht behauptet, dass C ++ Multithreading nicht unterstützt. Ich sagte, dass Threads nicht C ++ - spezifisch sind, da sie in vielen anderen Sprachen vorhanden sind. Ich habe gerade festgestellt, dass die beschriebenen Probleme für Threads als Schnittstelle zur Parallelität gelten.
Blaisorblade
Ich würde sagen, "Race Condition" ist ein besseres Wort für dieses Kernthema. Das heißt, dass Programmierer möglicherweise gar nicht an dem Concurrency Framework arbeiten oder es verwenden müssen. Wenn sie jedoch C ++ - Code schreiben und ihr Code möglicherweise von mehr als einem Thread aufgerufen wird, müssen sie über die Race-Bedingungen im Allgemeinen nachdenken. in all ihrem Code geschrieben.
Rwong
Es erinnert mich an eine Fehlkommunikation mit einem Kollegen, die vor Jahren stattgefunden hat. Ein Kollege fragte einen anderen Kollegen: Ist das (eine Funktion) threadsicher? Der andere Mitarbeiter antwortete mit Ja. Der Kollege, der danach gefragt hatte, verwendete es von mehreren Threads aus und erzielte unerwartete Ergebnisse (es stürzte nicht ab, aber mehrere Vorgänge wurden auf dasselbe Objekt angewendet). Es stellte sich heraus, dass der Mitarbeiter, der gefragt hat, nicht das mentale Modell dafür hat, was "thread-safe" bedeutet, und die Antwort als "Ich kann tun, was ich will" verwechselte.
Rwong
10

Die offensichtliche Antwort lautet constRichtigkeit: Da const/ volatilequalification ansteckend ist, muss jeder (direkt oder indirekt) aufrufende Code auch constrichtig sein, sobald ein Teil des Codes damit begonnen hat, ihn zu verwenden, oder er muss constexplizit verworfen werden.

Wie mit Ausnahmen ist dies jedoch offensichtlich letztendlich eine gute Sache . Dies gilt umso mehr, als es im Gegensatz zur Ausnahmesicherheit vom Compiler streng überprüft wird.

Konrad Rudolph
quelle
2
Außerdem ist const-correctness transparent: Es geht nur um den Typ, den Sie einer Funktion geben (die immer sichtbar ist), und der Compiler wird Sie anschreien, wenn Sie etwas falsch machen. Ich habe an undurchsichtigere Dinge gedacht, bei denen man keine Ahnung hat, dass etwas nicht stimmt, bis es zu spät ist (und selbst dann wird es schwierig sein, es herauszufinden). Aber Ihre Antwort ist trotzdem interessant und daher positiv bewertet.
Blaisorblade
10

Zeiger.

  • Zeigt der Zeiger auf den Speicher auf dem Stapel?
  • Zeigt der Zeiger auf den Speicher auf dem Heap?
  • Zeigt der Zeiger auf ein einzelnes Objekt?
  • Zeigt der Zeiger auf ein Array?
  • Zeigt der Zeiger auf eine Position in der Mitte eines Arrays?
  • Ist der Zeiger gültig?
  • Ist der Zeiger verstümmelt?
  • Welcher Code "besitzt" den Zeiger?
  • Soll das referenzierte Objekt manuell freigegeben werden? Wenn das so ist, wie?
Thomas Eding
quelle
1
+1 speziell wegen der Frage nach dem Zeigereigentum. Ohne intelligente Zeiger verbreitet sich das Eigentum wirklich im gesamten Team.
JKor
3

Eine andere Möglichkeit ist die Überlastung des Bedieners. Sobald ein Teil der Codebasis anfängt, an überladenen Operatoren zu basteln, neigt jeder dazu, zu erraten, was genau ein bestimmtes Objekt, mit dem er arbeitet, tatsächlich tut. Es verbreitet sich nicht explizit durch die Codebasis wie Ausnahmen und die Konstanten-Korrektheit, aber es kann definitiv zu Problemen führen, wenn das gesamte Team nicht auf derselben Seite darüber steht, wann, wie und warum es verwendet werden soll.

Evicatos
quelle
1

Das Einzige, was neben der (oben gezeigten) konstanten Korrektheit in den Sinn kommt, ist der Streaming-Zustand. Wenn Sie C ++ - Code schreiben, in dem Sie Objekte und Unterobjekte und Objekthierarchien verwenden, möchten Sie möglicherweise Daten an den / vom Bediener des Programms senden oder empfangen. Sie können einfache Streaming - Operationen schreiben, wird kompilieren und wird semantisch korrekt sein ...

std::ostream& operator<< (std::ostream&, MyClass const&) {...}
std::istream& operator>> (std::istream&, MyClass&) {...}

... Aber wenn Sie dies tun, werden Sie niemals die Garantie haben, dass das, was Sie schreiben (oder was am wichtigsten ist, lesen), dasselbe Format hat wie das, was der Client Ihnen sendet. Es gibt zu viele seltsame Fälle, die mit Streams vor sich gehen, noch schlimmer, wenn Sie Streams oder Stream-Flags als Argumente in Ihrer Funktionsaufrufkette übergeben müssen. Dies ist das Streaming von Klassen, das normalerweise implementiert wird. So kann Streaming als "heimtückisch" definiert werden, wie Sie den obigen Begriff verwendet haben, oder sogar als "viral" ( wenn auch nicht in gleichem Maße wie Konstanten-Korrektheit ).

Haben Sie ein Mitglied tief in Ihrer Klassenhierarchie, das a ist string? Überraschung, der Kunde sendet besser ein einzelnes Wort oder sonst. Haben Sie einige Nummern, die Sie serialisieren möchten? Sie sollten die Stream-Flags bei jeder Funktionsaufruftiefe überprüfen, speichern und wiederherstellen , da Sie nie wissen, wer der Idiot ist, der gerade seinen Stream auf Oktalausgabe gesetzt hat, bevor Sie Ihre Funktion aufrufen. Oder schlimmer noch - wer hat gerade so etwas wie setfillund genannt setwund damit die Eingabe / Ausgabe-Formatierung Ihres ersten - und nur Ihrer ersten - Integral-Member aufgehoben, weil sich diese Zustände nicht verbreiten . Oh und fragen wir nicht nach Streams und Internationalisierung.

Es gibt keine Warnung in der Sprache auch immer , dass Sie die richtige Art und Weise strömen, oder in die falsche Richtung, oder auch Streaming überhaupt . Haben Sie den Client-Code gefragt, ob ein Stream übergeben werden soll, an den die Datensicherung geschrieben werden soll? Sie können nicht wirklich erkennen, dass der Stream darauf verweist /dev/null. ( Auf der anderen Seite, Sie können unglaubliche Backup - Geschwindigkeit und Kompressionsraten behaupten , dass Art und Weise! )

Luis Machuca
quelle