(N) RVO является одним из самых простых для реализации оптимизаций.В большинстве соглашений о вызовах для возврата по значению вызывающая сторона резервирует пространство для возвращаемого объекта и затем передает скрытый указатель на функцию.Затем функция создает объект по указанному адресу.То есть kk += ii + jj;
переводится в нечто вроде:
Integer __tmp;
// __rtn this arg
Integer::operator+( &tmp, &ii, jj );
kk += __tmp;
Функция (в данном случае Integer::operator+
принимает первый скрытый аргумент __rtn
, который является указателем на неинициализированный блок памяти sizeof(Integer)
байт, где должен быть построен объект, второй скрытый аргумент this
, а затем аргумент функции в коде.
Затем реализация функции переводится в:
Integer::operator+( Integer* __rtn, Integer const * this, const Integer &rv) {
cout << "operator+" << endl;
new (__rtn) Integer(i + rv.i);
__rtn->print();
}
Поскольку соглашение о вызовах передает указатель, функции не нужно резервировать дополнительное пространство для локального целого числа, которое затем будет скопировано, поскольку она может просто встроить I
в вашем коде прямо в полученный указательи избегайте копирования.
Обратите внимание, что не во всех случаях компилятор может выполнять NRVO, в частности, если у вас есть два локальных объекта в функции и вы возвращаете любой из них в зависимости от условия, которое не является выводимым изкод (скажем, значение аргумента функции). Хотя вы могли бы сделать это, чтобы избежать RVO, на самом делечто это сделает ваш код более сложным, менее эффективным и сложным в обслуживании.