Consider below struct:
考虑下面的结构:
typedef struct _Index {
NSInteger category;
NSInteger item;
} Index;
If I use this struct as a property:
如果我将此结构用作属性:
@property (nonatomic, assign) Index aIndex;
@property(nonatomic,assign)索引aIndex;
When I access it without any initialization right after a view controller alloc init
, LLDB print it as:
当我在视图控制器分配init之后立即访问它而没有任何初始化时,LLDB将其打印为:
(lldb) po vc.aIndex
(category = 0, item = 0)
(lldb) po &_aIndex
0x000000014e2bcf70
I am a little confused, the struct already has valid memory address, even before I want to allocate one. Does Objective-C initialize struct automatically? If it is a NSObject, I have to do alloc init
to get a valid object, but for C struct, I get a valid struct even before I tried to initialize it.
我有点困惑,结构已经有了有效的内存地址,甚至在我想分配之前。 Objective-C是否自动初始化struct?如果它是一个NSObject,我必须使用alloc init来获取一个有效的对象,但对于C struct,我甚至在尝试初始化之前就得到了一个有效的结构。
Could somebody explains, and is it ok like this, not manually initializing it?
有人可以解释一下,是不是这样,不是手动初始化它?
2 个解决方案
#1
The semantics of the property are to copy the struct
, so it doesn't need to be allocated and initialized like an Objective-C object would. It's given its own space like a primitive type is.
该属性的语义是复制结构,因此不需要像Objective-C对象那样分配和初始化它。给它自己的空间就像原始类型一样。
You will need to be careful updating it, as this won't work:
您需要小心更新它,因为这不起作用:
obj.aIndex.category = 1;
Instead you will need to do this:
相反,你需要这样做:
Index index = obj.aIndex;
index.category = 1;
obj.aIndex = index;
This is because the property getter will return a copy of the struct
and not a reference to it (the first snippet is like the second snippet, without the last line that assigns the copy back to the object).
这是因为属性getter将返回结构的副本而不是对它的引用(第一个片段就像第二个片段,没有最后一行将副本分配回对象)。
So you might be better off making it a first class object, depending on how it will be used.
所以你可能最好把它变成第一类对象,具体取决于它的使用方式。
#2
To answer the subquestion, why you cannot assign to a structure component returned from a getter: (As a motivation this is, because I have read this Q several times.)
要回答这个问题,为什么你不能分配给一个从getter返回的结构组件:(作为动机,这是因为我已经多次读过这个Q.)
A. This has nothing to do with Cbjective-C. It is a behavior stated in the C standard. You can check it for simple C code:
答:这与Cbjective-C无关。这是C标准中规定的行为。您可以检查它是否有简单的C代码:
NSMakeSize( 1.0, 2.0 ).width = 3.0; // Error
B. No, it is not an improvement of the compiler. If it would be so, a warning would be the result, not an error. A compiler developer does not have the liberty to decide what an error is. (There are some cases, in which they have the liberty, but this are explicitly mentioned.)
B.不,这不是编译器的改进。如果是这样的话,结果就是警告,而不是错误。编译器开发人员无权自行决定错误是什么。 (在某些情况下,他们有*,但这是明确提到的。)
C. The reason for this error is quite easy:
C.出现此错误的原因非常简单:
An assignment to the expression
表达式的赋值
NSMakeSize( 1.0, 2.0 ).width
would be legal, if that expression is a l-value. A .
operator's result is an l-value, if the structure is an l-value:
如果表达式是l值,那将是合法的。一个 。运算符的结果是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.后缀表达式后跟。运算符和标识符指定结构或联合对象的成员。该值是指定成员的值,82)如果第一个表达式是左值,则该值是左值。
ISO/IEC 9899:TC3, 6.5.2.3
ISO / IEC 9899:TC3,6.5.2.3
Therefore it would be assignable, if the expression
因此,如果表达式,它将是可分配的
NSMakeSize( 1.0, 2.0 )
is an l-value. It is not. The reason is a little bit more complex. To understand that you have to know the links between .
, ->
and &
:
是一个l值。它不是。原因有点复杂。要了解您必须知道。, - >和&之间的链接:
In contrast to .
, ->
always is an l-value.
与。相反, - >始终是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)
Therefore - that is what footnote 83 explains – ->
, &
, and .
has a link:
因此 - 这就是脚注83解释的 - - >,&,和。有一个链接:
If you can calculate the address of a structure S
having a component C with the &
operator, the expression (&S)->C
is equivalent to S.C
. This requires that you can calculate the address of S
. But you can never do that with a return value, even it is a simple integer …
如果你可以使用&运算符计算具有组件C的结构S的地址,则表达式(&S) - > C等效于SC这要求您可以计算S的地址。但是你永远不能用返回值,即使它是一个简单的整数...
int f(void)
{
return 1;
}
f()=5; // Error
… or a pointer …
......或指针......
int *f(void)
{
return NULL;
}
f()=NULL; // Error
You always get the same error: It is not assignable. Because it is a r-value. This is obvious, because it is not clear,
你总是得到同样的错误:它不可分配。因为它是一个r值。这是显而易见的,因为它不清楚,
a) whether the way the compiler returns a value, esp. whether he does it in address space.
a)编译器返回值的方式,尤其是他是否在地址空间中做到了。
b) when the time the life time of the returned value is over
b)返回值的生命周期结束时间
Going back to the structure that means that the return value is a r-value. Therefore the result of the .
operator on that is a r-value. You are not allowed to assign a value to a r-value.
回到结构意味着返回值是一个r值。因此结果。运算符就是r值。您不能为r值赋值。
D. The solution
D.解决方案
There is a solution to assign to a "returned structure". One might decide, whether it is good or not. Since ->
always is an l-value, you can return a pointer to the structure. Dereferencing this pointer with the ->
operator has always an l-value as result, so you can assign a value to it:
有一个解决方案可以分配给“返回的结构”。人们可能会决定它是否好。由于 - >始终是l值,因此可以返回指向结构的指针。使用 - >运算符取消引用此指针始终具有l值作为结果,因此您可以为其分配值:
// obj.aIndex returns a pointer
obj.aIndex->category = 1;
You do not need @public
for that. (What really is a bad idea.)
你不需要@public。 (真是个坏主意。)
#1
The semantics of the property are to copy the struct
, so it doesn't need to be allocated and initialized like an Objective-C object would. It's given its own space like a primitive type is.
该属性的语义是复制结构,因此不需要像Objective-C对象那样分配和初始化它。给它自己的空间就像原始类型一样。
You will need to be careful updating it, as this won't work:
您需要小心更新它,因为这不起作用:
obj.aIndex.category = 1;
Instead you will need to do this:
相反,你需要这样做:
Index index = obj.aIndex;
index.category = 1;
obj.aIndex = index;
This is because the property getter will return a copy of the struct
and not a reference to it (the first snippet is like the second snippet, without the last line that assigns the copy back to the object).
这是因为属性getter将返回结构的副本而不是对它的引用(第一个片段就像第二个片段,没有最后一行将副本分配回对象)。
So you might be better off making it a first class object, depending on how it will be used.
所以你可能最好把它变成第一类对象,具体取决于它的使用方式。
#2
To answer the subquestion, why you cannot assign to a structure component returned from a getter: (As a motivation this is, because I have read this Q several times.)
要回答这个问题,为什么你不能分配给一个从getter返回的结构组件:(作为动机,这是因为我已经多次读过这个Q.)
A. This has nothing to do with Cbjective-C. It is a behavior stated in the C standard. You can check it for simple C code:
答:这与Cbjective-C无关。这是C标准中规定的行为。您可以检查它是否有简单的C代码:
NSMakeSize( 1.0, 2.0 ).width = 3.0; // Error
B. No, it is not an improvement of the compiler. If it would be so, a warning would be the result, not an error. A compiler developer does not have the liberty to decide what an error is. (There are some cases, in which they have the liberty, but this are explicitly mentioned.)
B.不,这不是编译器的改进。如果是这样的话,结果就是警告,而不是错误。编译器开发人员无权自行决定错误是什么。 (在某些情况下,他们有*,但这是明确提到的。)
C. The reason for this error is quite easy:
C.出现此错误的原因非常简单:
An assignment to the expression
表达式的赋值
NSMakeSize( 1.0, 2.0 ).width
would be legal, if that expression is a l-value. A .
operator's result is an l-value, if the structure is an l-value:
如果表达式是l值,那将是合法的。一个 。运算符的结果是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.后缀表达式后跟。运算符和标识符指定结构或联合对象的成员。该值是指定成员的值,82)如果第一个表达式是左值,则该值是左值。
ISO/IEC 9899:TC3, 6.5.2.3
ISO / IEC 9899:TC3,6.5.2.3
Therefore it would be assignable, if the expression
因此,如果表达式,它将是可分配的
NSMakeSize( 1.0, 2.0 )
is an l-value. It is not. The reason is a little bit more complex. To understand that you have to know the links between .
, ->
and &
:
是一个l值。它不是。原因有点复杂。要了解您必须知道。, - >和&之间的链接:
In contrast to .
, ->
always is an l-value.
与。相反, - >始终是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)
Therefore - that is what footnote 83 explains – ->
, &
, and .
has a link:
因此 - 这就是脚注83解释的 - - >,&,和。有一个链接:
If you can calculate the address of a structure S
having a component C with the &
operator, the expression (&S)->C
is equivalent to S.C
. This requires that you can calculate the address of S
. But you can never do that with a return value, even it is a simple integer …
如果你可以使用&运算符计算具有组件C的结构S的地址,则表达式(&S) - > C等效于SC这要求您可以计算S的地址。但是你永远不能用返回值,即使它是一个简单的整数...
int f(void)
{
return 1;
}
f()=5; // Error
… or a pointer …
......或指针......
int *f(void)
{
return NULL;
}
f()=NULL; // Error
You always get the same error: It is not assignable. Because it is a r-value. This is obvious, because it is not clear,
你总是得到同样的错误:它不可分配。因为它是一个r值。这是显而易见的,因为它不清楚,
a) whether the way the compiler returns a value, esp. whether he does it in address space.
a)编译器返回值的方式,尤其是他是否在地址空间中做到了。
b) when the time the life time of the returned value is over
b)返回值的生命周期结束时间
Going back to the structure that means that the return value is a r-value. Therefore the result of the .
operator on that is a r-value. You are not allowed to assign a value to a r-value.
回到结构意味着返回值是一个r值。因此结果。运算符就是r值。您不能为r值赋值。
D. The solution
D.解决方案
There is a solution to assign to a "returned structure". One might decide, whether it is good or not. Since ->
always is an l-value, you can return a pointer to the structure. Dereferencing this pointer with the ->
operator has always an l-value as result, so you can assign a value to it:
有一个解决方案可以分配给“返回的结构”。人们可能会决定它是否好。由于 - >始终是l值,因此可以返回指向结构的指针。使用 - >运算符取消引用此指针始终具有l值作为结果,因此您可以为其分配值:
// obj.aIndex returns a pointer
obj.aIndex->category = 1;
You do not need @public
for that. (What really is a bad idea.)
你不需要@public。 (真是个坏主意。)