C++ 在C++;?
我的意思是:C++ 在C++;?,c++,C++,我的意思是: int main() { void a() { // code } a(); return 0; } 现代C++——是的,与lambda! 当前版本的C++(C++ 11、C++ 14和C++ 17),可以在函数中以lambda形式:函数 int main() { // This declares a lambda, which can be called just like a function auto print_mes
int main()
{
void a()
{
// code
}
a();
return 0;
}
现代C++——是的,与lambda!
当前版本的C++(C++ 11、C++ 14和C++ 17),可以在函数中以lambda形式:
函数int main() {
// This declares a lambda, which can be called just like a function
auto print_message = [](std::string message)
{
std::cout << message << "\n";
};
// Prints "Hello!" 10 times
for(int i = 0; i < 10; i++) {
print_message("Hello!");
}
}
#include <functional> //For std::function
#include <iostream> //For std::cout
int main(){
int x = 4;
std::function<float(int)> divideByX = [x](int y){
return (float)y / (float)x; //x is a captured variable, y is an argument
}
std::cout << divideByX(3) << std::endl; //Prints 0.75
return 0;
}
然而,我会质疑实践。大家都知道(好了,现在你做的,不管是代码>:)/>代码> C++不支持本地函数,所以他们习惯不使用它们。然而,它们并没有被用于这种混乱。我会花相当长的时间在这段代码上,以确保它确实只允许本地函数。不太好 不,这是不允许的。C和C++都默认支持这个特性,但是TonyK指出(注释中)有GnU-C编译器的扩展,使C.</P> < P>中的行为不能在C++中定义另一个函数。 < P> NO./P> 你想干什么 解决方法:
int main(void)
{
struct foo
{
void operator()() { int a = 1; }
};
foo b;
b(); // call the operator()
}
从C++ 11开始,你可以使用适当的。有关更多详细信息,请参阅其他答案
旧答案:你可以,有点,但你必须作弊并使用虚拟类:
void moo()
{
class dummy
{
public:
static void a() { printf("I'm in a!\n"); }
};
dummy::a();
dummy::a();
}
对于所有的意图和目的,C++通过以下方式支持:1
intmain(){
自动f=[](){return 42;};
std::cout已经提到了局部类,但这里有一种方法可以让它们更像局部函数,使用操作符()重载和匿名类:
int main() {
struct {
unsigned int operator() (unsigned int val) const {
return val<=1 ? 1 : val*(*this)(val-1);
}
} fac;
std::cout << fac(5) << '\n';
}
正如其他人所提到的,您可以通过使用gcc中的gnu语言扩展来使用嵌套函数。如果您(或您的项目)坚持使用gcc工具链,那么您的代码在gcc编译器所针对的不同体系结构中大部分都是可移植的
然而,如果您可能需要使用不同的工具链来编译代码,那么我会远离这些扩展
在使用嵌套函数时,我也会小心处理。它们是管理复杂但内聚的代码块(这些代码块不是供外部/一般使用的)结构的漂亮解决方案。它们还非常有助于控制命名空间污染(对于冗长语言中的自然复杂/长类,这是一个非常重要的问题。)
但就像任何事情一样,它们也可能被滥用
令人遗憾的是,C/C++不支持作为标准的此类功能。大多数pascal变体和Ada都支持(几乎所有基于Algol的语言都支持)。JavaScript也是如此。Scala等现代语言也是如此。Erlang、Lisp或Python等古老语言也是如此
不幸的是,正如C/C++一样,Java(我的大部分生活都是靠它来挣钱的)没有
我在这里提到Java是因为我看到一些海报建议使用类和类的方法作为嵌套函数的替代品,这也是Java中典型的解决方法
简短回答:否。
这样做往往会在类层次结构上引入人为的、不必要的复杂性。在所有条件相同的情况下,理想的做法是让类层次结构(及其包含的名称空间和作用域)尽可能简单地表示实际域
嵌套函数有助于处理函数复杂度中的“私有”问题。如果没有这些功能,应该尽量避免将“私有”复杂度传播到类模型中
在软件(以及任何工程学科)中,建模都是一个权衡问题。因此,在现实生活中,这些规则(或者更确切地说是指导原则)都会有合理的例外。不过,请谨慎行事。所有这些技巧看起来(或多或少)作为局部函数,但它们不是那样工作的。在局部函数中,你可以使用它的超函数的局部变量。它是一种半全局函数。这些技巧中没有一种可以做到这一点。最接近的是c++0x中的lambda技巧,但它的闭包是在定义时间中绑定的,而不是在使用时间中绑定的。但是我们可以在main()中声明一个函数:
虽然语法正确,但有时可能导致“最麻烦的解析”:
#包括
结构单元
{
U():val(0){}
U(int val):val(val){}
int-val;
};
结构V
{
V(U a,U b)
{
STD::CUT让我在这里发布一个C++ 03的解决方案,我认为最干净的可能。*/P>
#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
struct { RETURN_TYPE operator () FUNCTION } NAME;
...
int main(){
DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
demoLambda();
DECLARE_LAMBDA(plus, int, (int i, int j){
return i+j;
});
cout << "plus(1,2)=" << plus(1,2) << endl;
return 0;
}
#定义声明LAMBDA(名称、返回类型、函数)\
结构{RETURN_TYPE operator()FUNCTION}名称;
...
int main(){
在C++中,你不能拥有局部函数。但是,C++ 11是。lambdas基本上是函数的变量。
lambda的类型为std::function
(,但在大多数情况下,您可以假设它是)。要使用此类型,您需要#include
std::function
是一个模板,将返回类型和参数类型作为模板参数,语法为std::function
。例如,std::function
是一个lambda,返回int
,并使用两个参数,一个std::string
d一个float
。最常见的是std::function
,它不返回任何内容,也不接受任何参数
声明lambda后,将使用语法lambda(参数)
像调用普通函数一样调用它
要定义lambda,请使用语法[captures](arguments){code}
(还有其他方法,但我在这里不赘述)。arguments
是lambda使用的参数,code
是调用lambda时应该运行的代码。通常您将[=]
或[&]
作为捕获。[=]
意味着您捕获由value定义的值范围内的所有变量,这意味着它们将保留声明lambda时拥有的值。[&]
意味着您通过引用捕获作用域中的所有变量,这意味着它们将始终具有其当前值,但如果从内存中删除这些变量,程序将崩溃。以下是一些示例:
#include <functional>
#include <iostream>
int main(){
int x = 1;
std::function<void()> lambda1 = [=](){
std::cout << x << std::endl;
};
std::function<void()> lambda2 = [&](){
std::cout << x << std::endl;
};
x = 2;
lambda1(); //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
lambda2(); //Prints 2 since that's the current value of x and x was captured by reference with [&]
std::function<void()> lambda3 = [](){}, lambda4 = [](){}; //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
//[](){} is the empty lambda.
{
int y = 3; //y will be deleted from the memory at the end of this scope
lambda3 = [=](){
std::cout << y << endl;
};
lambda4 = [&](){
std::cout << y << endl;
};
}
lambda3(); //Prints 3, since that's the value y had when it was captured
lambda4(); //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
//This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
//This is why you should be careful when capturing by reference.
return 0;
}
不能更改变量的值
auto fac = [] (unsigned int val) {
return val*42;
};
int main()
{
void a();
}
#include <iostream>
struct U
{
U() : val(0) {}
U(int val) : val(val) {}
int val;
};
struct V
{
V(U a, U b)
{
std::cout << "V(" << a.val << ", " << b.val << ");\n";
}
~V()
{
std::cout << "~V();\n";
}
};
int main()
{
int five = 5;
V v(U(five), U());
}
#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
struct { RETURN_TYPE operator () FUNCTION } NAME;
...
int main(){
DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
demoLambda();
DECLARE_LAMBDA(plus, int, (int i, int j){
return i+j;
});
cout << "plus(1,2)=" << plus(1,2) << endl;
return 0;
}
#include <functional>
#include <iostream>
int main(){
int x = 1;
std::function<void()> lambda1 = [=](){
std::cout << x << std::endl;
};
std::function<void()> lambda2 = [&](){
std::cout << x << std::endl;
};
x = 2;
lambda1(); //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
lambda2(); //Prints 2 since that's the current value of x and x was captured by reference with [&]
std::function<void()> lambda3 = [](){}, lambda4 = [](){}; //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
//[](){} is the empty lambda.
{
int y = 3; //y will be deleted from the memory at the end of this scope
lambda3 = [=](){
std::cout << y << endl;
};
lambda4 = [&](){
std::cout << y << endl;
};
}
lambda3(); //Prints 3, since that's the value y had when it was captured
lambda4(); //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
//This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
//This is why you should be careful when capturing by reference.
return 0;
}
#include <functional>
int main(){
int x = 4, y = 5;
std::function<void(int)> myLambda = [y](int z){
int xSquare = x * x; //Compiler error because x wasn't captured
int ySquare = y * y; //OK because y was captured
int zSquare = z * z; //OK because z is an argument of the lambda
};
return 0;
}
#include <functional>
int main(){
int x = 3, y = 5;
std::function<void()> myLambda = [x, &y](){
x = 2; //Compiler error because x is captured by value and so it's of type const int inside the lambda
y = 2; //OK because y is captured by reference
};
x = 2; //This is of course OK because we're not inside the lambda
return 0;
}
std::function<void()> lambda;
lambda(); //Undefined behavior because lambda is uninitialized
#include <functional> //Don't forget this, otherwise you won't be able to use the std::function type
int main(){
std::function<void()> a = [](){
// code
}
a();
return 0;
}
#include <functional> //For std::function
#include <iostream> //For std::cout
int main(){
int x = 4;
std::function<float(int)> divideByX = [x](int y){
return (float)y / (float)x; //x is a captured variable, y is an argument
}
std::cout << divideByX(3) << std::endl; //Prints 0.75
return 0;
}