Я видел эту ссылку, но я не прошу снижения производительности кода, использующего «extern». Я имею в виду без «extern», есть ли «переключение контекста» при использовании библиотеки C в C ++?
Есть ли какие-либо проблемы при использовании функций чистого C (не обернутых классом) в приложении C ++?
И C, и C ++ являются языком программирования. технические характеристики (написано на английском языке, см., например, n1570 для спецификации C11) и говорить не о производительности (а о поведении программы, то есть о семантика).
Тем не менее, вы, вероятно, будете использовать такой компилятор, как НКУ или же лязг которые не приносят никакого снижения производительности, поскольку создают одинаковое промежуточное внутреннее представление (например, GIMPLE для GCC и LLVM для Clang) для языков C и C ++, а также потому, что код на C и C ++ совместим с использованием ABIс и соглашения о вызовах.
На практике extern "C"
не изменяет соглашение о вызовах, но отключает название искажения. Однако его точное влияние на компилятор является специфическим для этого компилятора. Это может (или нет) отключить встраивание (но рассмотрим -flto
для оптимизации времени соединения в GCC).
Некоторые компиляторы C (например, tinycc) производить код с низкой производительностью. Четное НКУ или же лязг, при использовании с -O0
или без эксплицитно что позволяет оптимизация (например, прохождение -O1
или же -O2
и т.д. …) может привести к медленному коду (и оптимизации по умолчанию отключены с ним).
Кстати, C ++ был разработан для взаимодействия с C (и это сильное ограничение объясняет большинство недостатков C ++).
В некоторых случаях подлинный код C ++ может быть немного быстрее, чем соответствующий подлинный код C. Например, чтобы отсортировать массив чисел, вы будете использовать станд :: массив а также станд :: сортировать в подлинном C ++, и операции сравнения в сортировке могут быть встроенными. С кодом C, вы будете просто использовать QSort и каждое сравнение проходит через косвенный вызов функции (потому что компилятор не является встроенным qsort
, даже если в теории это могло бы …).
В некоторых других случаях подлинный код C ++ может быть немного помедленнее; например, несколько (но не все) реализации ::operator new
просто звонят malloc
(затем проверка на отказ), но не встроены.
На практике нет никакого наказания в вызове кода C из кода C ++ или кода C ++ из кода C, поскольку соглашения о вызовах совместимы.
C longjmp средство, вероятно, быстрее, чем выбрасывать исключения C ++, но они не имеют одинаковую семантику (см. разматывание стека) а также longjmp
плохо сочетается с кодом C ++.
Если вы так сильно заботитесь о производительности, напишите (на подлинном C и на подлинном C ++) дважды свой код и тест. Вероятно, вы заметите небольшое изменение (максимум несколько процентов) между C и C ++, поэтому Я бы не стал беспокоиться вообще (и ваши проблемы производительности практически неоправданны).
Переключение контекста это концепция, связанная с операционная система а также многозадачность и происходит на процессы Бег Машинный код исполняемый во время преимущественное право покупки. Как это исполнимый получается (из компилятора C, из компилятора C ++, из компилятора Go, из компилятора SBCL или являясь интерпретатором какого-либо другого языка, такого как Perl или байт-код Python), совершенно не имеет значения (поскольку переключение контекста может произойти в любой машина инструкция, во время прерывания). Прочитайте некоторые книги, как Операционные системы: Three Eeasy Pieces.
На базовом уровне, нет, вы не увидите никакого типа «переключения» производительности при вызове библиотеки C из кода C ++. Например, вызов из C ++ метода C, определенного в другом модуле перевода, должен иметь примерно такую же производительность, что и вызов того же метода, реализованного в C ++ (таким же образом, как в C), в другом модуле перевода.
Это потому, что общие реализации компиляторов C и C ++ в конечном итоге компилируют исходный код до нативного кода и вызывают extern "C"
Функция эффективно поддерживается с использованием того же типа call
это может произойти для вызова C ++. Соглашения о вызовах обычно основаны на платформе ABI и аналогичны в любом случае.
Помимо этого основного факта, при вызове функции C все еще могут быть некоторые недостатки производительности, в отличие от реализации той же функции в C ++:
extern "C"
и вызывается из кода C ++, как правило, не будет встроенным (поскольку по определению они не реализованы в заголовке), что препятствует целому ряду, возможно, очень мощной оптимизации0.std::string
в вашем коде C ++ вам нужно будет выбрать другой тип, чтобы передать его в код C — char *
распространено, но теряет информацию о явной длине, которая может быть медленнее, чем решение C ++. Многие типы не имеют прямого эквивалента C, поэтому вы можете столкнуться с дорогостоящим преобразованием.malloc
а также free
для динамического управления памятью, в то время как код C ++ обычно использует new
а также delete
(и обычно предпочитает скрывать эти вызовы за другими классами, насколько это возможно). Если вам нужно выделить память на одном языке, который будет освобожден на другом, это может привести к несоответствию, когда вам нужно будет перезвонить на «другой» язык, чтобы освободить его, или к ненужным копиям и т. Д.Вышеупомянутые проблемы применимы только при сравнении чистой реализации C ++ с реализацией C, и на самом деле это не означает, что при вызове C происходит снижение производительности: это действительно отвечает на вопрос «Почему можно было написать приложение в сочетании C и C ++ будет медленнее, чем чистый C ++? » Кроме того, вышеупомянутые проблемы в основном касаются очень коротких вызовов, где вышеуказанные издержки могут быть значительными. Если вы вызываете длинную функцию в C, это не проблема. «Несоответствие типов данных» может все еще кусать вас, но это может быть разработано на стороне C ++.
0 Интересно, что оптимизация во время соединения на самом деле позволяет методам C быть встроенный в C ++ код, что является мало упоминаемым преимуществом LTO. Конечно, это, как правило, зависит от сборки библиотеки C из исходного кода с соответствующими параметрами LTO.
1 Например, почти все, кроме стандартного типа макета.
2 Это, по крайней мере, частично смягчается тем фактом, что многие вызовы стандартной библиотеки C ++ в конечном итоге делегируют подпрограммам библиотеки C для «тяжелого» подъема, такого как std::copy
звонки memcpy
или же memset
когда это возможно и как большинство new
реализации в конечном итоге называют malloc
,
C ++ сильно вырос и сильно изменился с самого начала, но по своей конструкции он обратно совместим с C. Компиляторы C ++ обычно создаются из компиляторов C, но еще более модернизированы с оптимизация времени соединения. Я полагаю, что многие программы могут надежно смешивать код C и C ++, как в пользовательских пространствах, так и в используемых библиотеках. Я недавно ответил на вопрос это включало передачу указателя на функцию-член класса C ++ в библиотечную функцию, реализованную на C. Плакат сказал, что это работает для него. Поэтому возможно, что C ++ более совместим с C, чем думают программисты или пользователи.
Однако C ++ работает во многих различных парадигмах, которых нет в C, поскольку он объектно-ориентирован, и реализует целый спектр абстракций, новых типов данных и операторов. Некоторые типы данных легко переводимы (char *
C строка в std::string
), а другие нет. Этот раздел на GNU.org о параметрах компилятора C ++ может быть интересным
Я не был бы слишком обеспокоен или обеспокоен каким-либо снижением производительности при смешивании двух языков. Конечный пользователь и даже программист вряд ли заметят какие-либо измеримые изменения в производительности, если они не будут иметь дело с большими абстракциями данных.