3

我正在与代码“执行顺序”的概念搏斗,到目前为止我的研究还不够。我不确定我的措辞是否不正确,这个概念可能有更合适的术语。如果有人能阐明我下面的各种绊脚石,我将不胜感激。

我了解,如果您一个接一个地调用一个方法:

[self generateGrid1];
[self generateGrid2];

两种方法都运行,但 generateGrid1 不一定要等待 generateGrid2。但如果我需要它怎么办?假设 generateGrid1 进行一些复杂的计算(需要未知的时间)并填充 generateGrid2 用于其计算的数组?每次触发事件时都需要执行此操作,而不仅仅是一次初始化。

我需要一种按顺序调用方法的方法,但有一些方法等待其他方法。我研究过回调,但在我见过的所有示例中,这个概念总是与代表结合在一起。

我也不确定何时确定我不能合理地期望一行代码被及时解析以供使用。例如:

int myVar = [self complexFloatCalculation];
if (myVar <= 10.0f) {} else {} 

我如何确定某些事情是否需要足够长的时间来实施检查“在我开始我的事情之前是否完成了其他事情”。只是反复试验?

或者,也许我将一个方法作为另一个方法的参数传递?它是否在执行方法之前等待对参数进行评估?

[self getNameForValue:[self getIntValue]];
4

2 回答 2

6

我了解,如果您一个接一个地调用一个方法:

[self generateGrid1];
[self generateGrid2];

两种方法都运行,但 generateGrid1 不一定要等待 generateGrid2。但如果我需要它怎么办?

错误的。generateGrid1将运行,然后generateGrid2将运行。这种顺序执行是过程语言的基础。

从技术上讲,编译器可以重新排列语句,但前提是最终结果与原始结果无法区分。例如,看下面的代码:

int x = 3;
int y = 4;

x = x + 6;
y = y - 1;

int z = x + y;
printf("z is %d", z);

x+6不管是先发生还是先发生,都无关紧要y-1所写的代码除了计算之外没有使用任何一个中间值z,这可以按任何顺序发生。因此,如果编译器由于某种原因可以通过重新排列这些行来生成更高效的代码,则允许这样做。

但是,您永远无法看到这种重新排列的效果,因为一旦您尝试使用其中一个中间值(例如,记录它),编译器就会识别出该值正在被使用,并得到摆脱会破坏您的日志记录的优化。

所以真的,编译器不需要按照提供的顺序执行你的代码;它只需要生成与您提供的代码功能相同的代码。这意味着如果您将调试器附加到使用适当优化编译的程序,您实际上可以看到这些优化的效果。这会导致各种令人困惑的事情,因为调试器正在跟踪的源代码不一定与编译器生成的编译代码的代码逐行匹配。这就是为什么对于程序的调试版本几乎总是关闭优化的原因。

无论如何,关键是编译器只有在可以证明没有效果的情况下才能进行这些技巧。Objective-c 方法调用是动态绑定的,这意味着编译器绝对不能保证在调用该方法时在运行时实际会发生什么。由于编译器无法保证会发生什么,因此编译器永远不会重新排序 Objective-C 方法调用。但是,这又回到了我之前所说的相同原则:编译器可能会更改执行顺序,但前提是用户完全察觉不到。

换句话说,不要担心。您的代码将始终从上到下运行,每个语句都在等待它之前的语句完成。

于 2012-04-10T20:30:00.243 回答
5

通常,您在所描述的样式中看到的大多数方法调用都是同步的,这意味着它们将具有您想要的效果,按照语句编码的顺序运行,其中第二次调用只会在第一次调用完成运行,并且返回。

此外,当一个方法接受参数时,它的参数在方法被调用之前被评估。

于 2012-04-10T20:06:02.843 回答