Je vois des réponses valables ici, mais je vais entrer un peu plus dans les détails.
Allez au résumé ci-dessous pour la réponse à votre question principale si vous ne voulez pas parcourir tout ce mur de texte.
Abstraction
Alors, dans ce cas, qu'est-ce que je paie?
Vous payez pour l' abstraction . Etre capable d'écrire du code plus simple et plus convivial a un coût. En C ++, qui est un langage orienté objet, presque tout est un objet. Lorsque vous utilisez un objet, trois choses principales se produiront toujours sous le capot:
- Création d'objet, essentiellement allocation de mémoire pour l'objet lui-même et ses données.
- Initialisation d'objet (généralement via une
init()
méthode). Habituellement, l'allocation de mémoire se produit sous le capot comme la première chose de cette étape.
- Destruction d'objets (pas toujours).
Vous ne le voyez pas dans le code, mais chaque fois que vous utilisez un objet, les trois choses ci-dessus doivent se produire d'une manière ou d'une autre. Si vous deviez tout faire manuellement, le code serait évidemment beaucoup plus long.
Désormais, l'abstraction peut être faite efficacement sans ajouter de surcharge: l'inclusion de méthodes et d'autres techniques peuvent être utilisées à la fois par les compilateurs et les programmeurs pour supprimer les frais généraux d'abstraction, mais ce n'est pas votre cas.
Que se passe-t-il vraiment en C ++?
Le voici, décomposé:
- La
std::ios_base
classe est initialisée, qui est la classe de base pour tout ce qui concerne les E / S.
- L'
std::cout
objet est initialisé.
- Votre chaîne est chargée et transmise à
std::__ostream_insert
, qui (comme vous l'avez déjà compris par le nom) est une méthode de std::cout
(essentiellement l' <<
opérateur) qui ajoute une chaîne au flux.
cout::endl
est également passé à std::__ostream_insert
.
__std_dso_handle
est passé à __cxa_atexit
, qui est une fonction globale qui est responsable du «nettoyage» avant de quitter le programme. __std_dso_handle
lui-même est appelé par cette fonction pour désallouer et détruire les objets globaux restants.
Donc utiliser C == ne paie rien?
Dans le code C, très peu d'étapes se produisent:
- Votre chaîne est chargée et transmise
puts
via le edi
registre.
puts
est appelé.
Aucun objet nulle part, donc pas besoin d'initialiser / détruire quoi que ce soit.
Cela ne veut pas dire que vous n'êtes pas « payer » pour quoi que ce soit en C . Vous payez toujours pour l'abstraction, et l'initialisation de la bibliothèque standard C et la résolution dynamique de la printf
fonction (ou, en fait puts
, qui est optimisée par le compilateur puisque vous n'avez besoin d'aucune chaîne de format) se produisent toujours sous le capot.
Si vous deviez écrire ce programme en assemblage pur, il ressemblerait à ceci:
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
Ce qui aboutit essentiellement à l'invocation de l'appel write
système suivi de l' exit
appel système. Maintenant, ce serait le strict minimum pour accomplir la même chose.
Résumer
C est beaucoup plus simple et ne fait que le strict minimum nécessaire, laissant un contrôle total à l'utilisateur, qui est capable d'optimiser et de personnaliser complètement tout ce qu'il veut. Vous dites au processeur de charger une chaîne dans un registre, puis d'appeler une fonction de bibliothèque pour utiliser cette chaîne. Le C ++, quant à lui, est beaucoup plus complexe et abstrait . Cela présente un énorme avantage lors de l'écriture de code compliqué, et permet un code plus facile à écrire et plus convivial, mais cela a évidemment un coût. Il y aura toujours un inconvénient dans les performances en C ++ par rapport à C dans des cas comme celui-ci, car C ++ offre plus que ce qui est nécessaire pour accomplir ces tâches de base, et donc il ajoute plus de surcharge .
Répondre à votre question principale :
Est-ce que je paie ce que je ne mange pas?
Dans ce cas précis, oui . Vous ne profitez pas de tout ce que C ++ a à offrir plus que C, mais c'est simplement parce qu'il n'y a rien dans ce simple morceau de code que C ++ pourrait vous aider: c'est si simple que vous n'avez vraiment pas besoin de C ++ du tout.
Oh, et encore une chose!
Les avantages de C ++ peuvent ne pas sembler évidents à première vue, puisque vous avez écrit un programme très simple et petit, mais regardez un exemple un peu plus complexe et voyez la différence (les deux programmes font exactement la même chose):
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;
}
J'espère que vous pouvez clairement voir ce que je veux dire ici. Notez également comment en C vous devez gérer la mémoire à un niveau inférieur en utilisant malloc
et free
comment vous devez faire plus attention à l'indexation et aux tailles, et comment vous devez être très spécifique lors de la saisie et de l'impression.