Vedo alcune risposte valide qui, ma ho intenzione di approfondire un po 'di più i dettagli.
Vai al riepilogo di seguito per la risposta alla tua domanda principale se non vuoi passare attraverso questa intera parete di testo.
Astrazione
Quindi, in questo caso, per cosa sto pagando?
Stai pagando per l' astrazione . Essere in grado di scrivere un codice più semplice e più umano ha un costo. In C ++, che è un linguaggio orientato agli oggetti, quasi tutto è un oggetto. Quando usi qualsiasi oggetto, tre cose principali succederanno sempre sotto il cofano:
- Creazione di oggetti, sostanzialmente allocazione di memoria per l'oggetto stesso e i suoi dati.
- Inizializzazione dell'oggetto (di solito tramite un
init()metodo). Di solito l'allocazione della memoria avviene sotto il cofano come prima cosa in questo passaggio.
- Distruzione di oggetti (non sempre).
Non lo vedi nel codice, ma ogni volta che usi un oggetto tutte e tre le cose sopra devono accadere in qualche modo. Se dovessi fare tutto manualmente, il codice sarebbe ovviamente molto più lungo.
Ora, l'astrazione può essere realizzata in modo efficiente senza aggiungere spese generali: il metodo inline e altre tecniche possono essere utilizzate sia dai compilatori che dai programmatori per rimuovere le spese generali di astrazione, ma non è questo il caso.
Cosa sta realmente succedendo in C ++?
Eccolo, suddiviso:
- La
std::ios_baseclasse è inizializzata, che è la classe base per tutto ciò che riguarda l'I / O.
- L'
std::coutoggetto è inizializzato.
- La tua stringa viene caricata e passata a
std::__ostream_insert, che (come hai già capito con il nome) è un metodo di std::cout(sostanzialmente l' <<operatore) che aggiunge una stringa al flusso.
cout::endlviene anche passato a std::__ostream_insert.
__std_dso_handleviene passato a __cxa_atexit, che è una funzione globale responsabile della "pulizia" prima di uscire dal programma. __std_dso_handlestesso viene chiamato da questa funzione per deallocare e distruggere gli oggetti globali rimanenti.
Quindi usando C == non pagando nulla?
Nel codice C, stanno accadendo pochissimi passaggi:
- La tua stringa viene caricata e passata
putstramite il ediregistro.
puts viene chiamato.
Nessun oggetto da nessuna parte, quindi non è necessario inizializzare / distruggere nulla.
Questo però non significa che non stai "pagare" per nulla C . Stai ancora pagando per l'astrazione, e anche l'inizializzazione della libreria standard C e la risoluzione dinamica della printffunzione (o, in realtà puts, che è ottimizzata dal compilatore poiché non hai bisogno di alcuna stringa di formato) avvengono ancora sotto il cofano.
Se dovessi scrivere questo programma in puro assemblaggio sarebbe simile a questo:
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
Il che in pratica si traduce solo in invocazione della write syscall seguita dalla exitsyscall. Ora questo sarebbe il minimo indispensabile per realizzare la stessa cosa.
Riassumere
C è molto più semplice e fa solo il minimo indispensabile, lasciando il pieno controllo all'utente, che è in grado di ottimizzare completamente e personalizzare praticamente tutto ciò che vogliono. Dite al processore di caricare una stringa in un registro e quindi chiamate una funzione di libreria per usare quella stringa. Il C ++ invece è molto più complesso e astratto . Questo ha un enorme vantaggio quando si scrive un codice complicato e consente una scrittura più semplice e un codice più umano, ma ovviamente ha un costo. Ci sarà sempre uno svantaggio in termini di prestazioni in C ++ se confrontato con C in casi come questo, poiché C ++ offre più di quanto è necessario per svolgere tali compiti di base e quindi aggiunge più sovraccarico .
Rispondere alla domanda principale :
Sto pagando per quello che non sto mangiando?
In questo caso specifico, sì . Non stai sfruttando nulla di ciò che C ++ ha da offrire oltre a C, ma è solo perché non c'è niente in quel semplice pezzo di codice con cui C ++ potrebbe aiutarti: è così semplice che non hai davvero bisogno del C ++.
Oh, e solo un'altra cosa!
I vantaggi del C ++ potrebbero non sembrare ovvi a prima vista, poiché hai scritto un programma molto semplice e piccolo, ma guarda un esempio un po 'più complesso e vedi la differenza (entrambi i programmi fanno esattamente la stessa cosa):
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;
}
Spero che tu possa vedere chiaramente cosa intendo qui. Nota anche come in C devi gestire la memoria a un livello inferiore usando malloce freecome devi essere più attento riguardo all'indicizzazione e alle dimensioni, e come devi essere molto specifico quando prendi input e stampa.