Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 比较目标C中的块和函数_Objective C_Function_Block - Fatal编程技术网

Objective c 比较目标C中的块和函数

Objective c 比较目标C中的块和函数,objective-c,function,block,Objective C,Function,Block,当我学习目标C时,我的理解是新的和不完整的。块的概念与函数非常相似。它们甚至看起来几乎一模一样: 名为“multiply”的函数 #import <Foundation/Foundation.h> int multiply (int x, int y) { return x * y; } int main(int argc, char *argv[]) { @autoreleasepool { int result = multiply(7,

当我学习目标C时,我的理解是新的和不完整的。块的概念与函数非常相似。它们甚至看起来几乎一模一样:

名为“multiply”的函数

#import <Foundation/Foundation.h>

int multiply (int x, int y)
{

    return x * y;

}

int main(int argc, char *argv[]) {
    @autoreleasepool {

        int result = multiply(7, 4); // Result is 28.
        NSLog(@"this is the result %u",result);

        }
}
#导入
整数乘法(整数x,整数y)
{
返回x*y;
}
int main(int argc,char*argv[]){
@自动释放池{
int result=乘(7,4);//结果是28。
NSLog(@“这是结果%u”,结果);
}
}
名为“Multiply”的块

#import <Foundation/Foundation.h>

int (^Multiply)(int, int) = ^(int num1, int num2) {

    return num1 * num2;
};

int main(int argc, char *argv[]) {

    @autoreleasepool {

        int result = Multiply(7, 4); // Result is 28.
        NSLog(@"this is the result %u",result);
    }
}
#导入
整数(^Multiply)(整数,整数)=^(整数num1,整数num2){
返回num1*num2;
};
int main(int argc,char*argv[]){
@自动释放池{
int result=乘(7,4);//结果是28。
NSLog(@“这是结果%u”,结果);
}
}
我在网上发现了各种说法,如: 块被实现为Objective-C对象,但它们可以放在堆栈上,因此它们不一定必须是malloc(如果保留对块的引用,它将被复制到堆上)

雷·温德里奇说: “块是一级函数”

我不知道这一切意味着什么。我的例子表明,同样的事情可以作为块或函数来完成。有人能举一个例子,说明块可以做函数不能做的事情吗?反之亦然? 还是更微妙的事情,比如在内存中处理变量“result”的方式? 还是更快/更安全? 它们中的任何一个都可以用作类定义中的方法吗


谢谢。

块是Objective-C对象,函数不是。实际上,这意味着您可以将块从一段代码传递到另一段代码,如下所示:

NSArray *names = @[@"Bob", @"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
    NSLog(@"Hello, %@", name);
}];
在C语言中,通过传递指向函数的指针,可以实现类似的效果。但是,这样做与使用块之间的主要区别在于块可以捕获值。例如,在上面的示例中,如果我们想使用变量问候语:

NSString *greeting = @"Hello";
NSArray *names = @[@"Bob", @"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
    NSLog(@"%@, %@", greeting, name);
}];
在本例中,编译器可以看到块依赖于局部变量
greeting
,将“捕获”greeting的值,并将其与块一起存储(在本例中,这意味着保留并存储指向NSString的指针)。无论块最终在何处被使用(在本例中,在
[NSArray-EnumerateObjectsSusingBlock:
的实现中),它都可以像声明块时一样访问
问候语
变量这使您可以使用块范围内的任何局部变量,而不必担心将它们传递到块中。

要使用C中的函数指针执行同样的操作,
greeting
必须作为变量传入。但是,这不可能发生,因为调用方(在本例中为NSArray)不知道(尤其是在编译时)必须传递给函数的参数的确切数目。即使是这样,您也需要以某种方式将
greeting
的值以及您想要使用的所有其他局部变量传递给NSArray,这些变量很快就会变得毛茸茸的:

void greet(NSString *greeting, NSString *name) {
    NSLog(@"%@, %@", greeting, name);
}

// NSArray couldn't actually implement this
NSString *greeting = @"Hello";
NSArray *names = @[@"Bob", @"Alice"];
[names enumerateObjectsUsingFunction:greet withGreeting:greeting];
块是闭包——它们可以从周围范围捕获局部变量。这就是块(和其他现代语言中的匿名函数)和C中函数之间的巨大区别

下面是一个高阶函数的示例,
makeAdder
,它创建并返回一个“加法器”,一个将某个基数添加到其参数的函数。此基数由参数设置为
makeAdder
。因此,
makeAdder
可以返回具有不同行为的不同“加法器”:

typedef int (^IntFunc)(int);

IntFunc makeAdder(int x) {
    return ^(int y) { return x + y; }
}

IntFunc adder3 = makeAdder(3);
IntFund adder5 = makeAdder(5);

adder3(4); // returns 7
adder5(4); // returns 9
adder3(2); // returns 5
这对于C中的函数指针是不可能的,因为每个函数指针必须指向代码中的实际函数,其中有一个在编译时固定的有限数,每个函数的行为在编译时固定。因此,不可能根据运行时的值(如
makeAdder
does)创建几乎无限数量的潜在“加法器”。相反,您需要创建一个结构来保存状态


块不从周围范围捕获局部变量,就像在您的示例中一样,除了类型之外,它与普通函数没有太大区别。

块是对象。对象可以做的任何事情,块也可以。包括在运行时将对象关联到它们或将它们添加到集合中。块是一个匿名函数,在objective-c中可以将其视为对象。更重要的是,块可以捕获值(即,它可以是稳定的),但函数不能t@CrimsonChris-感谢您提供的示例,但我不知道“在运行时关联对象”是什么意思,也不知道集合是什么。说块像对象对你来说可能有意义,但我不明白如何让函数做同样的事情。@quellish-很明显你找到了苹果文档,我就是从它那里画出了我的例子的。但这又像是一个循环引用,因为它没有提到它们与函数Thank you igul222的区别。我年纪太大了,记得basic和PL1语言。在这些情况下,主循环中的变量通常可以通过子例程、函数或过程调用访问(与函数相同,但没有传递任何内容)。范围规则是最重要的,您必须记住有多少个层次,才能知道哪些变量在您之上(可访问),哪些变量在您之下(不可访问)。那么,哪些块可以访问任何变量呢?对顺便说一句,我尝试在我的评论中添加换行符,但在一行末尾添加两个空格没有任何作用。如何在这些评论中添加新段落?