Чтобы ответить на подвопрос, почему вы не можете присвоить структурный компонент возвращается из геттера: (как мотивация это, потому что я читал эту Q несколько раз.)
A. Это не имеет никакого отношения к делать с Cbjective-C. Это поведение указано в стандарте C. Вы можете проверить это для простого кода C:
NSMakeSize(1.0, 2.0).width = 3.0; // Error
B. Нет, это не улучшение компилятора. Если бы это было так, предупреждение было бы результатом, а не ошибкой. Разработчик компилятора не имеет права решать, что такое ошибка. (Есть некоторые случаи, в которых они имеют свободу, но это явно упомянуто.)
C. Причина этой ошибки довольно легко:
Уступка к выражению
NSMakeSize(1.0, 2.0).width
будет легальным, если это выражение является значением l.Результат A .
оператора является L-значением, если структура представляет собой L-значение:
A postfix expression followed by the .
operator and an identifier designates a member of a structure or union object. The value is that of the named member,82) and is an lvalue if the first expression is an lvalue.
ИСО/МЭК 9899: ТС3, 6.5.2.3
Поэтому было бы назначаемый, если выражение
NSMakeSize(1.0, 2.0)
является l-значением. Это не. Причина немного сложнее. Для того, чтобы понять, что вы должны знать связь между .
, ->
и &
:
В отличие от .
, ->
всегда является л-значение.
A postfix expression followed by the ->
operator and an identifier designates a member of a structure or union object. The value is that of the named member of the object to which the first expression points, and is an lvalue. 83)
Поэтому - это то, что сноска 83 объясняет - ->
, &
и .
есть ссылка:
Если вы можете вычислить адрес структуры S
, имеющей компонент С с оператором &
, то выражение (&S)->C
эквивалентно S.C
. Это требует, чтобы вы могли вычислить адрес S
. Но вы не можете сделать это с возвращаемым значением, даже это простое число ...
int f(void)
{
return 1;
}
f()=5; // Error
... или указатель ...
int *f(void)
{
return NULL;
}
f()=NULL; // Error
Вы всегда получаете ту же ошибку: он не может быть назначен. Потому что это r-значение. Это очевидно, потому что неясно,
a) является ли способ, которым компилятор возвращает значение, например. делает ли он это в адресном пространстве.
б) когда время время жизни возвращаемого значения над
Возвращаясь к структуре, что означает, что возвращаемое значение является т-значение. Поэтому результатом оператора .
является r-значение. Вам не разрешено присваивать значение r-значению.
Д. Раствор
Существует решение, чтобы присвоить «возвращаемой структуры». Можно решить, хорошо это или нет. Поскольку ->
всегда является значением l, вы можете вернуть указатель на структуру. Разыменование этого указателя с оператором ->
всегда L-значение, как результат, так что вы можете присвоить ему значение:
// obj.aIndex returns a pointer
obj.aIndex->category = 1;
Вам не нужно @public
для этого. (Что действительно плохой идеей.)
Я не понимаю, почему я не могу использовать 'obj.aIndex.category = 1;' – Wingzero
Потому что он установит новую категорию на копии объектов ' aIndex' (так что строка похожа на первые 2 строки моего второго примера). – trojanfoe
Я попробовал, и он выдает ошибку компилятора, говоря, что выражение не назначается. По-твоему, по-твоему? – Wingzero