Почему Apple разработала __block для записи auto var в блоке? - PullRequest
0 голосов
/ 05 апреля 2019

Мы можем прочитать auto var в блоке:

int aVar = 1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"theVar==%d", aVar);
});

Но не могу написать:

int aVar = 1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    aVar = 2;
    NSLog(@"theVar==%d", aVar);
});

Xcode показал: Variable is not assignable (missing __block type specifier).

Я знаю, что когда нет __block, auto var передается в блок как копия, поэтому он доступен только для чтения. И с __block его адрес передается в блок.

Но я не могу понять, почему Apple должна спроектировать это так? Просто скопировать адрес в блок не в порядке? Есть ли потенциальная проблема, если auto var in block без __block доступен для записи?

1 Ответ

4 голосов
/ 07 апреля 2019

Это не так просто, как «с __block передачей адреса в блок», потому что блок, который захватывает переменную, может пережить область, в которой он создан, и локальная переменная продолжительности автоматического хранения станет недействительной в концеиз области видимости, поэтому просто захват его адреса не будет работать.

Переменная, объявленная с __block, на самом деле включает в себя скрытую структуру за кулисами, которую при необходимости можно «переместить» из стека в кучу.таким образом, он может пережить область, в которой он был создан, и есть дополнительные скрытые поля, которые компилятор создает за кулисами, чтобы позволить кому-то, получающему доступ к переменной, выяснить реальное местоположение переменной (стека или кучи) в это время.Кроме того, блоки должны управлять памятью копии переменной в куче.Таким образом, определение переменной __block требует дополнительной памяти по сравнению с самой переменной, а доступ к переменной __block требует большего уровня косвенности и большей логики управления памятью для задействованных блоков.Это дополнительное осложнение следует использовать только при необходимости;следовательно, переменные, захваченные блоками, по умолчанию не __block.

...