Я вижу некоторые правильные ответы здесь, но я собираюсь немного подробнее рассказать о них.
Перейдите к приведенной ниже сводке, чтобы найти ответ на свой главный вопрос, если вы не хотите проходить через всю эту стену текста.
абстракция
В таком случае, за что я плачу?
Вы платите за абстракцию . Возможность писать более простой и понятный для человека код обходится дорого. В C ++, который является объектно-ориентированным языком, почти все является объектом. Когда вы используете какой-либо предмет, под капотом всегда будут происходить три главных вещи:
- Создание объекта, в основном выделение памяти для самого объекта и его данных.
- Инициализация объекта (обычно с помощью какого-либо
init()
метода). Обычно выделение памяти происходит под капотом, как первое на этом этапе.
- Разрушение объекта (не всегда).
Вы не видите этого в коде, но каждый раз, когда вы используете объект, все три вышеперечисленных вещи должны как-то происходить. Если бы вы делали все вручную, код, очевидно, был бы намного длиннее.
Теперь абстракция может быть сделана эффективно, без добавления накладных расходов: компиляция методов и другие методы могут использоваться как компиляторами, так и программистами для устранения издержек абстракции, но это не ваш случай.
Что на самом деле происходит в C ++?
Вот оно, сломано:
std::ios_base
Класс инициализируется, который является базовым классом для всего I / O связаны между собой .
std::cout
Объект инициализируется.
- Ваша строка загружается и передается
std::__ostream_insert
, что (как вы уже поняли по названию) является методом std::cout
(в основном <<
оператором), который добавляет строку в поток.
cout::endl
также передается std::__ostream_insert
.
__std_dso_handle
передаются __cxa_atexit
, что глобальная функция , которая отвечает за «чистку» перед выходом из программы. __std_dso_handle
сама эта функция вызывается для освобождения и уничтожения оставшихся глобальных объектов.
Так что использование C == ничего не платит?
В коде C происходит очень мало шагов:
- Ваша строка загружается и передается
puts
через edi
реестр.
puts
вызывается.
Нет объектов нигде, следовательно, не нужно ничего инициализировать / уничтожать.
Это, однако, не означает, что вы ничего не «платите» в Си . Вы по-прежнему платите за абстракцию, а также за инициализацию стандартной библиотеки C и динамическое разрешение, при котором printf
функция (или, собственно puts
, оптимизированная компилятором, поскольку вам не нужна строка формата) все еще происходит под капотом.
Если бы вы написали эту программу в чистом виде, она бы выглядела примерно так:
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
Что в основном приводит только к write
вызову системного вызова, за которым следует exit
системный вызов. Теперь это был бы минимум для достижения того же.
Подвести итоги
C гораздо более простой и выполняет только необходимый минимум, оставляя полный контроль над пользователем, который способен полностью оптимизировать и настраивать практически все, что он хочет. Вы говорите процессору загрузить строку в регистр, а затем вызываете библиотечную функцию для использования этой строки. С ++, с другой стороны, более сложный и абстрактный . Это имеет огромное преимущество при написании сложного кода и позволяет легче писать и более дружественный к человеку код, но это, очевидно, обходится дорого. В C ++ всегда будет недостаток производительности по сравнению с C в подобных случаях, поскольку C ++ предлагает больше, чем необходимо для выполнения таких базовых задач, и, следовательно, добавляет больше накладных расходов .
Отвечая на ваш главный вопрос :
Я плачу за то, что не ем?
В данном конкретном случае да . Вы не пользуетесь преимуществами того, что C ++ может предложить больше, чем C, но это только потому, что в этом простом куске кода нет ничего, что могло бы помочь вам в C ++: это настолько просто, что вам действительно не нужен C ++ вообще.
Ох, и еще одна вещь!
На первый взгляд преимущества C ++ могут показаться неочевидными, поскольку вы написали очень простую и небольшую программу, но посмотрите на более сложный пример и увидите разницу (обе программы делают одно и то же):
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;
}
Надеюсь, вы можете ясно увидеть, что я имею в виду здесь. Также обратите внимание на то, как в C вы должны управлять памятью на более низком уровне с помощью malloc
и free
как вам нужно быть более осторожным с индексированием и размерами, и как вы должны быть очень точными при вводе и печати.