当你声明一个指针时,它会创建一个新对象吗?

时间:2014-05-31 03:50:34

标签: objective-c

如果这是一个新手问题,请饶恕我,我来自Java,指针的概念对我来说似乎很陌生。

SKView * skView = (SKView *)self.view;
skView.showsFPS = YES;
skView.showsNodeCount = YES;

所以......代码告诉我skView是一个指针,但你可以访问指针所指向的对象。不应该以正确的方式执行代码,因为* skView意味着您正在访问指针指向的实际对象吗?

*skView.showsFPS = YES;
*skView.showsNodeCount = YES;

这是指针的C编程语言指南

int x = 1, y = 2, z[10];
int *ip; /* ip is a pointer to int */
ip = &x; /* ip now points to x */
y = *ip; /* y is now 1 */
*ip = 0; /* x is now 0 */
ip = &z[0]; /* ip now points to z[0] */

它说你需要使用那个* ip关键字才能访问指针的值?我在这里很困惑......

3 个答案:

答案 0 :(得分:2)

您对dot syntax感到困惑。

你写了这个:

skView.showFPS = YES;

您认为skView.showFPS表示“访问showFPSstruct变量union中的字段skView”,因为这就是C中的含义(和C ++)。

但你错了。在该语句中,skView是指向Objective-C对象的指针。当编译器在指向对象的指针之后看到一个点时,它会以两种方式之一转换表达式。

如果表达式是赋值的左侧,如示例所示,那么它将表达式转换为:

[skView setShowFPS:YES];

另一方面,假设表达式分配的左侧。例如:

BOOL showingFPS = skView.showFPS;

然后编译器将表达式转换为:

BOOL showingFPS = [skView showFPS];

换句话说,编译器将点表示法(当应用于对象指针时)转换为getter或setter消息,具体取决于上下文。

我在解释中省略了一些细节。如果需要,您可以覆盖getter和setter消息的名称,using an @property declaration

如果您确实想直接访问对象的实例变量,并且您可以看到实例变量的声明,则可以执行以下操作:

skView->_showFPS = YES;

或等效地:

(*skView)._showFPS = YES;

(注意.比前缀*绑定得更紧,所以你需要括号。)

但是,这几乎总是一个坏主意。您几乎不应该直接从对象外部访问对象的实例变量。甚至在对象的实现中,使用带有访问器方法的属性而不是裸实例变量通常更好。

答案 1 :(得分:1)

对于常规C,您的排序是正确的。

如果你要做这样的事情:

struct my_struct {
    int a;
    int b;
};

struct my_struct my_object = {1, 2};
struct my_struct * my_ptr = &my_object;

然后您可以通过取消引用指针来访问成员:

int n = (*my_ptr).a;

或不使用->运算符取消引用它:

int n = my_ptr->a;

但是你用Objective-C看到的点语法与此不同。编译器知道您正在处理Objective-C对象,并将其转换为消息调用。

从某种意义上说,Objective-C使用的语法与您可以用来访问常规C struct成员的语法相同,但实际上做了一些非常不同的事情,这有点令人遗憾。另一方面,正确引入该语法是因为C语言程序员所熟悉的事情与struct s类似。无论哪种方式,重要的是不要混淆两者。

答案 2 :(得分:1)

你写道:

  

我来自Java,指针的概念对我来说似乎很陌生。

Java和Objective-C中的对象都是引用类型;这是对象类型的变量,它包含一个引用(或指针或地址)到其他地方创建的对象结构。这是与值类型的契约,例如int,其中值类型变量的内容是实际值的表示。

Java和Objective-C之间的区别在于,后者使用*在声明中显示引用/指针部分,从C开始。

考虑以下Java片段:

class MyClass { ... }

MyClass one = new MyClass ();
MyClass two = one;
MyClass three;

在此作为Java程序员之后,您将知道:one引用MyClass的新实例; two引用与one相同的对象,而不是one引用的对象的副本; three未定义或null取决于它是什么类型(字段,本地)变量。

Objective C的工作方式完全相同,等效代码:

@interface MyClass
...
@end

MyClass *one = [MyClass new];
MyClass *two = one;
MyClass *three;

并且这三个变量具有相同的值(three在ARC下始终为nil,并且无论变量类型如何都不会未定义。

引用(指针)指示符*仅出现在Objective-C中的对象变量类型中;就像在Java中一样,但与C中不同,跟随对象的引用(“解除引用”)是自动的。所以在Java中你可以写:

one.equals(two)

在Objective-C中调用equals方法,它将是:

[one isEqual:two]

Objective-C中的属性;这是两个方法,一个setter和一个getter,它们一起就像一个变量;可以使用点速记:

int x = one.intProperty; // equivalent to int x = [one intProperty];
one.intProperty = 42;    // equivalent to [one setIntProperty:42];

这与C对结构字段访问的.的使用不同,虽然类似,因此使用相同的语法。

如果Objective-C中的类具有公共实例变量(通常应该避免使用属性作为良好封装的一部分),那么可以使用C用于访问来自a的字段的->运算符来访问这些变量。指向结构的指针:

one->instanceVariable

和C一样,您可以使用以下方式明确表示尊重:

(*one).instanceVariable

但是从来没有必要这样做,最好避免。

我认为这回答了你提出的所有问题。