Тут наведено перелік операторів, що використовуються у мовах програмуванняC й C++. Усі наведені оператори присутні у C++. Якщо оператор також використовується у мові С, це буде відмічено у стовпчику "Присутній у С". Стовпчик "Можливість перевантаження" має сенс лише для мови C++, оскільки C не підтримує перевантаження операторів.
За відсутності перевантаження, для операторів &&, ||, та , (оператор кома), існує точка перебігу після обчислення першого операнду.
C++ також містить наступні оператори приведення типівconst_cast, static_cast, dynamic_cast, та reinterpret_cast, які в таблиці не подані задля скорочення. Форматування цих операторів означає, що рівень їх пріоритету не є важливим.
Більшість операторів C та C++ також використовуються у мовах C#, Java, Perl, та PHP з тими самими пріоритетом, асоціативністю та семантикою.
Таблиця
В даній таблиці символи a, b, та c - це будь-які значення (літерали, значення змінних, або повернені значення), імена об'єктів або інші значення, що мають адресу.
"Можливість перевантаження" означає, що даний оператор може бути перевантажений засобами C++, але не у мові С, оскільки вона не підтримує перевантаження операторів. "Присутній у C" означає що даний оператор існує і має семантичний зміст у мові C.
Примітка: для перетворень, які є визначені користувачем, тип що повертається повинен обов'язково збігатися з ім'ям оператора.
Виділення пам'яті
newtype
Так
Ні
void*T::operatornew(size_tx);
void*operatornew(size_tx);
Виділення пам'яті під масив
newtype[n]
Так
Ні
void*T::operatornew[](size_tx);
void*operatornew[](size_tx);
Вивільнення пам'яті
delete a
Так
Ні
voidT::operatordelete(void*x);
voidoperatordelete(void*x);
Вивільнення пам'яті масиву
delete[] a
Так
Ні
voidT::operatordelete[](void*x);
voidoperatordelete[](void*x);
Примітки:
↑Оператор отримання остачі працює лише з цілочисельними операндами, для чисел з рухомою комою має бути застосована відповідна бібліотечна функція (наприклад fmod).
↑ абВ контексті потоків введення/виведення бібліотеки iostream, автори часто називають оператори << та >> як “вставити в” або "внесення в потік" та “взяти з” або "винесення з потоку", відповідно.
↑ абВідповідно до стандарту C99, зсув вправо від'ємного числа залежить від його конкретної реалізації. У більшості реалізацій застосовується арифметичний зсув, але можливим є і логічний зсув.
↑Приклад можна знайти у "Implementing operator->* for Smart Pointers"
by Scott Meyers.
↑ аб
У випадку, коли оператор ->* працює за замовчуванням, параметр R буде методом-покажчиком на метод класу Т і повернене значення нагадуватиме деякий функтор, що готовий до виклику з параметрами методу (і тільки ними).
↑При визначенні розміру змінної, круглі дужки не обов'язкові, вони потрібні лише при визначенні розміру типу даних. Однак, зазвичай, вони все одно вживаються.
↑У мові C++ визначено оператор alignof, тоді як у C _Alignof. Обидва оператори мають однакову семантику.
Пріоритет операторів
У наступній таблиці вказано пріоритет та асоціативність усіх операторів мов C та C++ (якщо будь-який з вказаних операторів існує в мовах Java, Perl, PHP або інший сучасних мовах, його пріоритет, скоріш за все, буде таким самим). Оператори вказані в порядку зниження пріоритету зверху вниз. Зниження пріоритету відноситься до пріоритету обчислень. В процесі обчислення виразу, оператор вказаний у певному рядку таблиці, буде обчислений раніше за оператор, вказаний у будь-якому нижчому за нього рядку. Оператори, вказані в одній комірці, обчислюються з однаковим пріоритетом в порядку їх запису у виразі. При перевантаженні, пріоритет оператора не змінюється.
Синтакс виразів у мовах C та C++ визначається контекстно-вільною граматикою. Наведена вище таблиця отримана на основі граматики.
Слід зазначити, що в деяких випадках таблиця пріоритетів на працює. Наприклад, тернарний умовний оператор дозволяє використовувати як свій середній операнд будь-який довільний вираз, попри те, що за таблицею його пріоритет вищий, ніж у операторів присвоєння та коми. Таким чином вираз a ? b , c : d інтерпретується саме як a ? (b, c) : d, а не (a ? b), (c : d) (що не мало б сенсу). Крім того, слід зазначити, що безпосередній результат виразу, який перетворює типи, не може бути операндом sizeof. Тому, sizeof (int) * x інтерпретується як (sizeof(int)) * x, а не sizeof ((int) *x).
Створення тестової помилки (винятку) (тільки у C++)
18
,
Кома
Зліва направо
Примітки
Таблиця пріоритету визначає порядок застосування (поєднання) операторів у складних виразах, коли цей порядок не заданий явно за допомогою круглих дужок.
Наприклад, вираз ++x*3 без застосування правил пріоритету має певну двозначність. Таблиця пріоритету каже нам, що: x тісніше 'пов'язаний' з ++, ніж з *, тому, щоб не робив оператор ++ (зараз чи пізніше), він робитиме це ТІЛЬКИ з x (а не з x*3); це еквівалентно виразу (++x, x*3).
Аналогічним чином, для виразу 3*x++, де постфіксний оператор інкременту ++ хоча і призначений діяти ПІСЛЯ обчислення усього виразу, але таблиця пріоритетів ясно вказує, що не зважаючи на це, інкрементується ТІЛЬКИ x (а не 3*x); це еквівалентно виразу подібному до (tmp=3*x, ++x, tmp), де tmp є тимчасовим значенням.
Пріоритет та поєднання
Зобразимо проблему пріоритету операторів та їх поєднання у вигляді діаграми. Завданням компілятора є перетворення цієї діаграми у вираз, в якому декілька унарних операторів ( назвемо їх 3+( . ), 2*( . ), ( . )++ та ( . )[ i ] ) конфліктують за поєднання з y. Проблема вирішується за допомогою таблиці пріоритету, яка дозволяє сформувати остаточний набір виразів: ( . )[ i ] діє тільки на y, ( . )++ діє тільки на y[i], 2*( . ) діє тільки на y[i]++ та 3+( . ) діє 'тільки' на 2*((y[i])++). Важливо зазначити, що таблиця дозволяє визначити, який з виразів буде використаний кожним з операторів, але відповіді на питання "КОЛИ кожний оператор вступить в дію", таблиця не дає. В даному прикладі оператор ( . )++ діє тільки на y[i] за правилами таблиці, але самі по собі рівні поєднання не визначають час виконання суфікса ++ (оператор ( . )++ буде використаний лише після обчислення у виразі елементу y[i]).
Низка багатосимвольних операторів отримують власні "імена", побудовані з назв операторів для кожного свого символу. Наприклад, оператори += та -= часто називаються плюс дорівнює та мінус дорівнює, а не "присвоєння суми" та "присвоєння різниці", що було б громіздкіше.
Поєднання операторів у C та C++ визначається скоріше граматикою мови (викладеною у відповідних стандартах), а не таблицею пріоритету. Це створює деякі приховані конфлікти. Наприклад, у мові С, синтаксис для виразу з умовним переходом є таким:
у двох мовах граматично розбивається по різному. У мові C цей вираз є синтаксичною помилкою, але багато компіляторів розбивають вираз так:
e=((a<d?a++:a)=d)
що є семантичною помилкою, оскільки результат виразу з умовним переходом (яким може бути a++) не є адресованим значенням (lvalue). У C++ це розбивається як:
e=(a<d?a++:(a=d))
що є правильним виразом.
Пріоритет побітових операторів було розкритиковано [1]. Концептуально, оператори & and | є арифметичними операторами, подібними до + and *.
Вираз a&b==7 синтаксично розбивається як a&(b==7), коли вираз a+b==7 розбивається як (a+b)==7. Це потребує частішого застосування круглих дужок.
Синоніми операторів C++
C++ визначає[1]
набір ключових слів, які можуть діяти як псевдоніми деяких операторів: and (&&), bitand (&), and_eq (&=), or (||), bitor (|), or_eq (|=), xor (^), xor_eq (^=), not (!), not_eq (!=), compl (~). Їх можна використовувати тим самим чином як і ті символи, які вони замінюють, оскільки псевдонім це не тільки той самий оператор, але під іншим ім'ям, але скоріше це є текстовий еквівалент імені відповідного оператора. Наприклад, bitand можна використати для заміни не тільки побітового оператора але і оператора отримання адреси і навіть використати для вказання типів посилань (наприклад: int bitand ref = n; замість int &ref = n; ).
Специфікація ANSI для мови C резервує ці ключові слова як макроси препроцесора у заголовному файліiso646.h. З метою збереження сумісності із C, у мові C++ передбачено заголовний файл ciso646, додавання якого не дає жодного ефекту.