Меню сайта
Наш опрос
Оцените мой сайт
Всего ответов: 6
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » 2014 » Июль » 22 » Virtual inline методы C++
15:13
Virtual inline методы C++

C++ даёт возможность определять встраиваемые (inline) функции и методы. Реализация таких функций будет встраиваться в другие функции по месту вызова (за исключением некоторых случаев, когда это невозможно). Как правило, в конечном исполняемом файле или динамической библиотеке отдельной реализации таких функций не генерируется.Другой замечательный механизм, предоставляемый языком C++ — это виртуальные методы. Эти методы участвуют в полиморфизме. Вы может вызывать такие функции из производного класс по указателю или ссылке на базовый. Достигается это путём помещения указателя на конкретную реализацию в таблицу виртуальных функций, которая помещается компилятором в известное ему место относительно полиморфного указателя или ссылке (конкретная реализация не стандартизирована и зависит от компилятора).Стандарт C++ позволяет применять модификатор virtual к inline функциям. Тут мы наталкиваемся на неоднозначность. Как в таблицу виртуальных функций попадёт указатель, если тело функции не генерируется? Ответ на этот вопрос также не стандартизирован и зависит от компилятора. Давайте попробуем разобраться.Итак, допустим у нас есть такой код extern "C" void exFunction(int);class Base{public: virtual int doSomething(int x, int y) { return x + y; }};class Child : public Base{public: virtual int doSomething(int x, int y) { return x * y; }};extern "C" void run(){ Base base; int result = base.doSomething(1, 2); exFunction(result); Child child; result = child.doSomething(2, 2); exFunction(result);}Функция exFunction нужна лишь для того, чтобы компилятор не соптимизировал наши вычисления.Я буду использовать компилятор g++ 4.7.2 и операционную систему Debian GNU/Linux 7.0 (wheezy) 64 bit.Сохраним исходный текст в файл test.cpp соберём динамическую библиотеку с помощью командыg++ -g -O2 -shared -fPIC test.cppЯ собираю динамическую библиотеку, чтобы было меньше мусора в дампе. Кроме того, я включил оптимизацию и отладочные символы. Посмотрим результат компиляции с помощью программы objdump. objdump -d a.out00000000000006e0 <run>: 6e0: 48 83 ec 08 sub $0x8,%rsp 6e4: bf 03 00 00 00 mov $0x3,%edi 6e9: e8 e2 fe ff ff callq 5d0 <exFunction@plt> 6ee: bf 04 00 00 00 mov $0x4,%edi 6f3: 48 83 c4 08 add $0x8,%rsp 6f7: e9 d4 fe ff ff jmpq 5d0 <exFunction@plt>Как видим, компилятор не обратил внимание на модификатор virtual и просто встроил inline методы в код, соптимизировав сложение и умножение.Теперь добавим в код полиморфизма. extern "C" void exFunction(int);class Base{public: virtual int doSomething(int x, int y) { return x + y; }};class Child : public Base{public: virtual int doSomething(int x, int y) { return x * y; }};extern "C" void run(){ Base base; int result = base.doSomething(1, 2); exFunction(result); Child child; result = child.doSomething(2, 2); exFunction(result); Base * polymorphic = &child; result = polymorphic->doSomething(3, 3); exFunction(result);}Скомпилируем и посмотрим на дизассемблированный код. 0000000000000a50 <run>: a50: 48 83 ec 18 sub $0x18,%rsp a54: bf 03 00 00 00 mov $0x3,%edi a59: e8 e2 fe ff ff callq 940 <exFunction@plt> a5e: 48 8b 05 e3 03 20 00 mov 0x2003e3(%rip),%rax # 200e48 <_DYNAMIC+0x228> a65: bf 04 00 00 00 mov $0x4,%edi a6a: 48 83 c0 10 add $0x10,%rax a6e: 48 89 04 24 mov %rax,(%rsp) a72: e8 c9 fe ff ff callq 940 <exFunction@plt> a77: 48 8b 04 24 mov (%rsp),%rax a7b: 48 89 e7 mov %rsp,%rdi a7e: ba 03 00 00 00 mov $0x3,%edx a83: be 03 00 00 00 mov $0x3,%esi a88: ff 10 callq *(%rax) a8a: 89 c7 mov %eax,%edi a8c: e8 af fe ff ff callq 940 <exFunction@plt> a91: 48 83 c4 18 add $0x18,%rsp a95: c3 retq a96: 90 nop a97: 90 nop a98: 90 nop a99: 90 nop a9a: 90 nop a9b: 90 nop a9c: 90 nop a9d: 90 nop a9e: 90 nop a9f: 90 nop0000000000000aa0 <_ZN4Base11doSomethingEii>: aa0: 8d 04 16 lea (%rsi,%rdx,1),%eax aa3: c3 retq aa4: 90 nop aa5: 90 nop aa6: 90 nop aa7: 90 nop aa8: 90 nop aa9: 90 nop aaa: 90 nop aab: 90 nop aac: 90 nop aad: 90 nop aae: 90 nop aaf: 90 nop0000000000000ab0 <_ZN5Child11doSomethingEii>: ab0: 89 f0 mov %esi,%eax ab2: 0f af c2 imul %edx,%eax ab5: c3 retq ab6: 90 nop ab7: 90 nopТеперь мы видим, что компилятор сгенерировал реализации для виртуальных методов и использовал виртуальную таблицу для третьего вызова. При этом первые два вызова остались встроенными.Вообще говоря, компилятор всегда будет генерировать тело inline функции, если где-либо в программе требуется её адрес (явно или неявно). При этом, Вы можете расчитывать на встраивание virtual inline функции, если не используете для её вызова указатель или ссылку.Я провёл подобное исследование с Visual C++, и оказалось, что этот компилятор ведёт себя аналогичным образом.


Девченки - проститутки Магнитогорска в гостиницу. Адекватные цены.
Просмотров: 244 | Добавил: admin | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
Форма входа
Календарь
«  Июль 2014  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей