Я думаю, что вы путаете две вещи: перегрузку операторов и то, как вы определяете оператор для определенного пользователем типа.Перегрузка оператора не нова;он уже существует в C, где +
перегружен на int
, unsigned
int
, long
, unsigned long
, float
, double
и long double
.В C ++ вы можете добавить операторы для пользовательских типов, определив функцию с именем operator+
, чтобы список перегрузок был длиннее.И чтобы сделать вещи более связными, способ, которым компилятор разрешает перегрузку, состоит в том, чтобы добавить синтезированные сигнатуры по линиям operator+(int, int)
в список перегрузок.Если затем разрешение перегрузки заканчивается выбором одной из этих синтезированных сигнатур, он использует встроенный оператор, генерирующий любой необходимый машинный код (который может включать вызов функции на уровне машинного кода).Тот факт, что он выбирает одну из «встроенных» перегрузок, имеет последствия в остальной части кода: пользовательский оператор считается вызовом функции с соответствующими точками последовательности и всеми остальными, а компилятор неразрешено делать любые предположения относительно его семантики - в частности, компилятор не может предполагать, что пользовательский operator+
является ассоциативным или коммутативным.Встроенный оператор (с очень немногими исключениями) не вводит никаких точек последовательности, и компилятор знает его семантику и может оптимизировать его в результате.
Обратите внимание, что сгенерированный машинный код может не быть таким разным.Я использовал машины, где компилятору приходилось вызывать функцию для умножения int
s, и компилятор может (и часто будет) вставлять определенный пользователем оператор.Что изменило, так это правила, о которых я упоминал выше: наличие точек последовательности в пользовательских операторах и тот факт, что компилятор не может делать предположения относительно различных математических законов, которые могут применяться.