int foo(int x)То есть тело такой функции пишется внутри другой функции, и она может ссылать на ее переменные.
{
int y = 0;
void bar(int z)
{
y += x*z;
}
bar(1);
bar(2);
return y;
}
В C++ такого счастья нет. Может такого не сделали из-за того, что в Сях стек устроен немного по-другому, нежели в Паскале (в любом случае - не оправдание), может Бьярн счел это "не тру". Конечно, можно написать локальный класс, у которого будет нужная функция, но которому придется вручную передавать нужные переменные - но это неудобно, да и выглядит ужасно. Вот как-то так:
int foo(int x)Но с новым стандартом этот способ стал гораздо короче в записи:
{
int y = 0;
class foobar
{
public:
bar(int &y, int x) : y(y), x(x)
{
}
void operator ()(int z)
{
y += x*z;
}
private:
int &y, x;
} bar(y, x);
bar(1);
bar(2);
return y;
}
int foo(int x)Если сравнить с кодом, приведенным в начале - отличия минимальны! А уж если оно выглядит как утка, плавает как утка и крякает как утка - то чем не
{
int y = 0;
auto bar = [&](int z)
{
y += x*z;
};
bar(1);
bar(2);
return y;
}
6 комментариев:
Это называется closures. Что делать, если ты из корневой функции возвратишь указатель на внутреннюю функцию, и потом где-нибудь попытаешься ее вызвать? Что будет с высвобожденным стеком локальных переменных корневой функции?
Что делать, если ты из корневой функции возвратишь указатель на внутреннюю функцию, и потом где-нибудь попытаешься ее вызвать?
Я же не буду этого делать. К чему этот вопрос?
to wecanstoptrain
Насколько я понимаю, этот код практически эквивалентен коду с ручным созданием класса. Эффекты будут теже, как если вернуть экземпляр foobar. Очевидно, если там есть ссылки, то все будет плохо :)
Кстати, если вернуть указатель на лок функцию в дельфях, то все тоже будет плохо, если она использует локальные переменные корневой функции
Ассоциация с анонимными методами из C#. Языковое расширение без которого можно прожить :-) Думаю, что такие участки кода многие макросами отрабатывают.
Эта локальная функция называется замыканием (closure).
В новой редакции то, что вы написали (auto bar = ...) называется неименованным фунциональным объектом (lambda).
Вот здесь очень доступно
http://blogs.msdn.com/b/vcblog/archive/2008/10/28/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx
В boost'е есть реализация и closure, и lambda, но пользоваться было не очень удобно и компилировалось не быстро.
В си есть nested functions... активно используются например в grub, правда постоянно вызывают ругань компилятора... :)
http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
В C++ имхо функторы всякие лучше будут. :) Доступ к локальным переменным - не нужен, лишнее это.
Отправить комментарий