Ночные эксперименты с компилятором.

Return Value Optimization (RVO).

Написал простейший код, имитирующий работу умного указателя С++.

 #include <iostream> 
using namespace std;

class IntPtr {
public:
IntPtr(int i) {
pInt = new int(i);
cout << "Construct" << endl;
}

IntPtr(const IntPtr &c) {
int t = c.getInt();
pInt = new int(t);
cout << "Copy" << endl;
}

IntPtr& operator= (const IntPtr &c) {
*pInt = c.getInt();
cout << "Operator =" << endl;
return *this;
}

~IntPtr() {
delete pInt;
cout << "Delete" << endl;
}

int getInt() const {
return *pInt;
}

private:
int *pInt;
};

IntPtr foo(const IntPtr &n) {
int i = n.getInt() + 4;
IntPtr r(i);
return r;
}

int main() {
IntPtr i(6);
IntPtr n = foo(i);
cout << "Result: " << n.getInt() << endl;
}

А теперь попробуем собрать код. Сначала соберем с Return Value Optimization, RVO. Потом без нее.

 Tims-MacBook-Pro:coolp tim$ clang++ coolp.cpp -o coolp
Tims-MacBook-Pro:coolp tim$ ./coolp
Construct
Construct
Result: 10
Delete
Delete
Tims-MacBook-Pro:coolp tim$ 

В данном случае, с включенной RVO, создается i в main(), после чего создается r в foo() И все! Далее r возвращается как есть без копирования. Т.е. n в main() и r в foo() это одно и то же. Т.е. компилятор «понял», что это один и тот же объект и сделал его таким.

Отлично! Теперь попробуем собрать этот же код без RVO. Отключается опцией -fno-elide-constructors.

Tims-MacBook-Pro:coolp tim$ clang++ coolp.cpp -o coolp2 -fno-elide-constructors
Tims-MacBook-Pro:coolp tim$ ./coolp2 
Construct
Construct
Copy
Delete
Copy
Delete
Result: 10
Delete
Delete
Tims-MacBook-Pro:coolp tim$

Как видно из листинга выше, возвращаемый объект r у нас скопировался аж целых 2 раза. Первый раз при возврате из функции и второй раз из r в n. Это лишние накладные расходы.

Т.е. с включенным RVO компилятор может подавлять создание новых объектов при возврате из функций. И правда зачем создавать новый объект и копировать в него инфу из старого, если и так понятно, что можно вернуть старый объект.

Хорошо, что компилятор умный, правда? 🙂

Оставьте комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *