inline функции?
4994
20
язык c++
Как известно если компилятор по каким бы то ни было причинам не может сделать функцию(определённую как inline) встраиваемой, он делает из неё обычную. Как узнать, что inline функция оттранслировалась действительно как встраиваемая? Ну и в догонку, можноли определять перегружаемые встроенные функции?
Заранее спасибо за ответы.
Swindler
Перегрузка определяетяся на этапе компиляции, так что по идее должно быть можно перегруженные функции делать inline

Насчет того как узнать, можно например дебаггером посмотреть
CoolUser
Насчет того как узнать, можно например дебаггером посмотреть
А как дебагером смотреть? По f11 в неё заходит так же, как в обыкновенную.
Swindler
Ассемблерный листинг посмотри, там call есть или нет
CoolUser
004020F3 call @ILT+55(ddfgg) (0040103c)
функция ddfgg причём call есть в любом случае, хотя примерчик книжный, сорри если туплю, просто с ассемблером туго у меня...
CoolUser
ok.
листинг
// nevill.cpp : Defines the entry point for the console application.
//
#include <iostream.h>

//using namespace std;


inline int even(int a){

return ! (a%2);

}



int main()
{
if(even(10)) cout << "true" <<endl;else cout << "false" <<endl;

return 0;
}
Disassembly

0040106A call @ILT+20(even) (00401019)
0040106F add esp,4
00401072 test eax,eax
00401074 je main+43h (00401093)
00401076 push offset @ILT+10(endl) (0040100f)
0040107B push offset string "true" (00425024)
00401080 mov ecx,offset cout (004289c0)
00401085 call ostream::operator<< (00401470)
0040108A mov ecx,eax
0040108C call @ILT+0(ostream::operator<<) (00401005)
00401091 jmp main+5Eh (004010ae)
00401093 push offset @ILT+10(endl) (0040100f)
00401098 push offset string "false" (0042501c)
0040109D mov ecx,offset cout (004289c0)
004010A2 call ostream::operator<< (00401470)
004010A7 mov ecx,eax
004010A9 call @ILT+0(ostream::operator<<) (00401005)
19:
20: return 0;
004010AE xor eax,eax
21: }
004010B0 pop edi
004010B1 pop esi
004010B2 pop ebx
004010B3 add esp,40h
004010B6 cmp ebp,esp
004010B8 call __chkesp (00403550)
004010BD mov esp,ebp
004010BF pop ebp
004010C0 ret
здесь она точняк должна быть inline
Swindler
Лень смотреть. Цель мучений какова?
CoolUser
3D конечно-разностная аппроксимация...
Очень сильно влияет на быстродействие...
Swindler
да брось, лишняя пара call/ret ничего тебе не даст. оптимизировать надо алгоритмику, а не такие ньюасны реализации как inline
CoolUser
:хехе:Ага 1000х1000х1000 сетка в каждой точке вычисляются 30 переменных, при вычислении каждой(порядка 20 000 раз - время) вызываются функции, это не пара call/ret,
с алгоритмом то всё как раз понятно.
Swindler
вызов функции дает оверхеад на одну пару call/ret. inline ничего не даст
CoolUser
Какая разница, всё равно каждый раз запускается механизм вызова ф-ции и возврата значения, а не подстановка на этапе компиляции, лана спорить не буду, если лень переборю, запущу тестик с многократным вызовом обычных и инлайн и время замерю, рез-ты выложу.
Swindler
Так компилер должен выдавать соответствующий ворнинг. Например Борланд выдает примерно такое:
Warning 8026. такая растакая фанкшен are not expanded inline.
Может у тебя это предупреждение отключено?
Swindler
&gt; Ну и в догонку, можноли определять перегружаемые встроенные функции?

Можно. Но опять-таки, если компилятор "не сможет", то сделает из нее обычную.

Вот (на английском):
http://msdn2.microsoft.com/en-us/magazine/cc301407.aspx
Swindler
В приведенном листенге она точно не inline.
Хотя с точки зрения кода такая функция может быть inline - следовательно смотри настройки компилятора - там обязательно есть флажок типа такого Disable Inline Expansions или disable inline in debug или что-то подобное.
Оптимизацией всетаки стоит начинать заниматся тогда, когда вы точно замерили где ваша программа тратит много времени - для этого есть соответствующие инструменты.
Обычно 5% кода выполняются 95% времени и только для этих двух процентов имеет смысл делать оптимизацию. Вашу функцию лучше переписать так ! (a&amp;1) если компилятор этого за вас не сделал!
bravot
Пример из книжки, поэтому должна быть inline. Почему Вы думаете что ф-ция из листинга не может быть инлайн? Пользую VS 6.0 поставил самый высокий уровень варнингов, ничего насчёт инлайн дебагер не выдаёт. Вообще всегда думал, что встраиваемая функция не сильно отличается от обыкновенной, кроме того что не должна содержать запрещённых конструкций(static var,switch,for,e.t.c.), зависит от компилятора.
Swindler
> 0040106A call @ILT+20(even) (00401019)

Это не inline. Хотя по коду нет никаких препятствий для этого.
Нужно копать VS 6.0
Anomander
Вот нарыл
Microsoft Specific

The __inline keyword is equivalent to inline.

Even with __forceinline, the compiler cannot inline code in all circumstances. The compiler cannot inline a function if:

The function or its caller is compiled with /Ob0 (the default option for debug builds).
The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).
The function has a variable argument list.
The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
The function returns an unwindable object by value, when compiled with /GX, /EHs, or /EHa.
The function receives an unwindable copy-constructed object passed by value, when compiled with /GX, /EHs,, or /EHa.
The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions can be inlined to a default depth of eight calls. To change the inlining depth, use inline_depth pragma.
The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
The function is also marked with the naked __declspec modifier.
If the compiler cannot inline a function declared with __forceinline, it generates a level 1 warning (4714).

Recursive functions can be substituted inline to a depth specified by the inline_depth pragma. After that depth, recursive function calls are treated as calls to an instance of the function. The inline_recursion pragma controls the inline expansion of a function currently under expansion. See the Inline-Function Expansion (/Ob) compiler option for related information.

END Microsoft Specific
Таким образом получается, что в отладочном режиме фиг добьёшься чтобы функция встраивалась. Интересно а как понять что в релизе всё успешно скомпилилось...
Swindler
Именно это я и имел в виду, твоя inline функция исключена благодаря компиляции в режиме отладчика. Однако получить из Release build отладочную инфу тоже можно, поищи опции - нужно разрешить генерацию debug symbols (Programm database) и в линковке флажок поставить. Тогда твоя функция будет определенно inline. Можно кстати еще и ассемблерный код в студии получить - все тамже в опциях поройся.
Только учти локальные переменные могут так извратится компилятором, что довольно сложно потом по ним судить что-то, но в принципе свою функцию найдешь я думаю
bravot
На последнего...

Есть еще один вариант, правда, совсем не в стиле С++, но все же, может, окажется уместным:

#define _EVEN_(a) (!((a) % 2))