Ich sehe hier einige gültige Antworten, aber ich werde ein bisschen mehr ins Detail gehen.
Wechseln Sie zur folgenden Zusammenfassung, um die Antwort auf Ihre Hauptfrage zu erhalten, wenn Sie nicht die gesamte Textwand durchgehen möchten.
Abstraktion
Wofür bezahle ich in diesem Fall?
Sie bezahlen für die Abstraktion . Die Möglichkeit, einfacheren und menschlicheren Code zu schreiben, ist mit Kosten verbunden. In C ++, einer objektorientierten Sprache, ist fast alles ein Objekt. Wenn Sie ein Objekt verwenden, passieren immer drei Dinge unter der Haube:
- Objekterstellung, im Grunde Speicherzuordnung für das Objekt selbst und seine Daten.
- Objektinitialisierung (normalerweise über eine
init()
Methode). Normalerweise erfolgt die Speicherzuweisung als erstes in diesem Schritt unter der Haube.
- Objektzerstörung (nicht immer).
Sie sehen es nicht im Code, aber jedes Mal, wenn Sie ein Objekt verwenden, müssen alle drei oben genannten Dinge irgendwie passieren. Wenn Sie alles manuell machen würden, wäre der Code offensichtlich viel länger.
Jetzt kann die Abstraktion effizient durchgeführt werden, ohne zusätzlichen Aufwand zu verursachen: Methoden-Inlining und andere Techniken können sowohl von Compilern als auch von Programmierern verwendet werden, um Abstraktionskosten zu entfernen. Dies ist jedoch nicht der Fall.
Was passiert wirklich in C ++?
Hier ist es, aufgeschlüsselt:
- Die
std::ios_base
Klasse wird initialisiert. Dies ist die Basisklasse für alles, was mit E / A zu tun hat.
- Das
std::cout
Objekt wird initialisiert.
- Ihre Zeichenfolge wird geladen und an übergeben. Dies ist
std::__ostream_insert
(wie Sie bereits anhand des Namens herausgefunden haben) eine Methode std::cout
(im Grunde der <<
Operator), mit der dem Stream eine Zeichenfolge hinzugefügt wird.
cout::endl
wird auch an übergeben std::__ostream_insert
.
__std_dso_handle
wird an übergeben __cxa_atexit
, eine globale Funktion, die für das "Reinigen" vor dem Beenden des Programms verantwortlich ist. __std_dso_handle
selbst wird von dieser Funktion aufgerufen, um die Zuordnung und Zerstörung verbleibender globaler Objekte aufzuheben.
Also mit C == nichts bezahlen?
Im C-Code werden nur sehr wenige Schritte ausgeführt:
- Ihre Zeichenfolge wird geladen und
puts
über das edi
Register weitergeleitet.
puts
wird gerufen.
Keine Objekte irgendwo, daher muss nichts initialisiert / zerstört werden.
Dies bedeutet jedoch nicht, dass Sie für nichts in C "bezahlen" . Sie zahlen immer noch für die Abstraktion, und auch die Initialisierung der C-Standardbibliothek und die dynamische Auflösung der printf
Funktion (oder tatsächlich puts
, die vom Compiler optimiert wird, da Sie keine Formatzeichenfolge benötigen) finden immer noch unter der Haube statt.
Wenn Sie dieses Programm in reiner Assemblierung schreiben würden, würde es ungefähr so aussehen:
jmp start
msg db "Hello world\n"
start:
mov rdi, 1
mov rsi, offset msg
mov rdx, 11
mov rax, 1 ; write
syscall
xor rdi, rdi
mov rax, 60 ; exit
syscall
Dies führt im Grunde nur zum Aufrufen des write
Systemaufrufs, gefolgt vom exit
Systemaufruf. Nun dies wäre das absolute Minimum , das Gleiche zu erreichen.
Zusammenfassen
C ist weitaus einfacher und stellt nur das Nötigste dar, das benötigt wird, und überlässt dem Benutzer die volle Kontrolle, der in der Lage ist, im Grunde alles zu optimieren und anzupassen, was er will. Sie weisen den Prozessor an, eine Zeichenfolge in ein Register zu laden und dann eine Bibliotheksfunktion aufzurufen, um diese Zeichenfolge zu verwenden. C ++ hingegen ist viel komplexer und abstrakter . Dies hat einen enormen Vorteil beim Schreiben von kompliziertem Code und ermöglicht ein einfacheres Schreiben und einen benutzerfreundlicheren Code, ist jedoch offensichtlich mit Kosten verbunden. In solchen Fällen wird die Leistung in C ++ im Vergleich zu C immer einen Nachteil haben, da C ++ mehr bietet, als für die Ausführung solcher grundlegenden Aufgaben erforderlich ist, und somit mehr Overhead verursacht .
Beantwortung Ihrer Hauptfrage :
Zahle ich für das, was ich nicht esse?
In diesem speziellen Fall ja . Sie nutzen nichts, was C ++ mehr zu bieten hat als C, aber das liegt nur daran, dass dieser einfache Code nichts enthält, bei dem C ++ Ihnen helfen könnte: Es ist so einfach, dass Sie C ++ wirklich überhaupt nicht benötigen.
Oh, und noch eine Sache!
Die Vorteile von C ++ sind auf den ersten Blick vielleicht nicht offensichtlich, da Sie ein sehr einfaches und kleines Programm geschrieben haben. Schauen Sie sich jedoch ein etwas komplexeres Beispiel an und sehen Sie den Unterschied (beide Programme machen genau das Gleiche):
C :
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
return *(int*)a - *(int*)b;
}
int main(void) {
int i, n, *arr;
printf("How many integers do you want to input? ");
scanf("%d", &n);
arr = malloc(sizeof(int) * n);
for (i = 0; i < n; i++) {
printf("Index %d: ", i);
scanf("%d", &arr[i]);
}
qsort(arr, n, sizeof(int), cmp)
puts("Here are your numbers, ordered:");
for (i = 0; i < n; i++)
printf("%d\n", arr[i]);
free(arr);
return 0;
}
C ++ :
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void) {
int n;
cout << "How many integers do you want to input? ";
cin >> n;
vector<int> vec(n);
for (int i = 0; i < vec.size(); i++) {
cout << "Index " << i << ": ";
cin >> vec[i];
}
sort(vec.begin(), vec.end());
cout << "Here are your numbers:" << endl;
for (int item : vec)
cout << item << endl;
return 0;
}
Hoffentlich können Sie klar sehen, was ich hier meine. Beachten Sie auch, wie Sie in C den Speicher auf einer niedrigeren Ebene verwalten müssen malloc
und free
wie Sie bei der Indizierung und Größe vorsichtiger sein müssen und wie Sie bei der Eingabe und beim Drucken sehr spezifisch sein müssen.