在目标c中需要指针对象

时间:2013-08-01 10:56:44

标签: ios objective-c memory-management

一个非常基本的问题......但要理解这些概念真的非常重要.. 在c ++或c语言中,我们通常不使用指针变量来存储值。即,值只是按原样存储:

int a=10;

但是在ios sdk中,在目标c中,我们使用的大多数对象都是通过用它们表示指针来初始化的,如下所示:

NSArray *myArray=[NSArray array];

所以,在我看来,问题是,使用指针对象的好处需要是什么(这就是我们在这里所称的,如果它是不正确,拜托,告诉).. 另外,当使用指针对象进行分配时,我有时会对内存分配基础感到困惑。我可以在任何地方寻找好的解释吗?

5 个答案:

答案 0 :(得分:16)

  

在c ++或c语言中,我们通常不使用指针变量来存储值

我会接受#34;或C"部分出局。 C ++程序员不赞成使用原始指针,但C程序员不会。 C程序员喜欢指针,并认为它们是解决所有问题的不可避免的银弹解决方案。 (不,不是真的,但指针在C中仍然常常使用。)

  

但是在ios sdk中,在目标c中,我们使用的大多数对象都是通过用它们表示指针来初始化的

哦,仔细看看:

  

大部分对象

更接近:

  

<强> 物体

所以你在谈论Objective-C对象,amirite? (忽略C标准基本上将所有值和变量描述为&#34;对象&#34;的微妙之处。)

它实际上只是在Objective-C中始终是指针的Objective-C对象。由于Objective-C是C的严格超集,所以在编写iOS应用程序(或OS X应用程序或任何其他基于Objective-C的程序)时,所有C语言和编程技术仍然适用。它是毫无意义,多余,浪费,因此,甚至被认为是错误来编写类似

的内容
int *i = malloc(sizeof(int));
for (*i = 0; *i < 10; ++*i)

因为我们在Objective-C土地上。基元(或更正确的#34;普通的旧数据类型&#34;使用C ++术语)仍然遵循&#34;如果不需要则不使用指针&#34;规则。

  

使用指针对象有什么好处和需要

所以,为什么他们是必要的:

Objective-C是一种面向对象的动态语言。这两种强烈相关的语言属性使程序员可以利用polymorphismduck-typingdynamic binding等技术(是的,这些是超链接,点击它们)。< / p>

实现这些功能的方式使得必须通过指向它们的指针来表示所有对象。让我们看一个例子。

编写移动应用程序时的一项常见任务是从服务器检索某些数据。现代基于Web的API使用JSON数据交换格式来序列化数据。这是一种简单的文本格式,可以将其解析(例如,使用NSJSONSerialization类)到各种类型的数据结构及其相应的集合类中,例如NSArrayNSDictionary 。这意味着JSON解析器类/方法/函数必须返回泛型,可以表示两者数组和字典的内容。

那么现在呢?我们不能返回非指针NSArrayNSDictionary结构(Objective-C对象实际上只是我知道Objective-C工作的所有平台下的简单旧C结构),因为它们具有不同的大小,它们具有不同的存储器布局等。编译器无法理解代码。这就是为什么我们返回指向id类型的通用Objective-C对象的指针。

C标准要求指向struct(以及对象)的指针具有相同的表示和对齐要求(C99 6.2.5.27),即。即指向任何结构的指针可以安全地转换为指向任何其他结构的指针。因此,这种方法是正确的,我们现在可以返回任何对象。使用运行时内省,还可以动态确定对象的确切类型(类),然后相应地使用它。

为什么他们方便或更好(在某些方面)比非指针

使用指针,不需要传递同一对象的多个副本。创建大量副本(例如,每次将对象分配给或传递给函数时)都会很慢并导致性能问题 - 中等复杂的对象(例如视图或视图控制器)可能会有数十个副本实例变量,因此单个实​​例可以测量数百个字节。如果采用对象类型的函数调用在紧密循环中被调用数千或数百万次,那么重新分配和复制它是非常痛苦的(无论如何对于CPU),并且它更容易和更直接。只需传入一个指向对象的指针(它的大小较小,因此可以更快地复制)。此外,Objective-C是一种参考计数语言,甚至可以阻止&#34;反正过度复制。保留和释放优于显式复制和释放。

  

当使用指针对象进行分配时,我有时会对内存分配基础感到困惑

那么即使没有指针,你也很可能很困惑。不要把它归咎于指针,而是程序员错误; - )

所以这里......

玩得开心! : - )

答案 1 :(得分:3)

任何比int或char或类似更复杂的东西通常都会被传递为 甚至在C.中的指针。在C中你当然可以传递一个数据结构 从功能到功能,但这很少见。

请考虑以下代码:

struct some_struct {
    int an_int;
    char a_char[1234];
};

void function1(void)
{
    struct some_struct s;
    function2(s);
}

void function2(struct some_struct s)
{
    //do something with some_struct s
}

some_struct数据将被放在function1的堆栈中。当function2 被称为数据将被复制并放在堆栈上以便在function2中使用。 它要求数据在堆栈上的数量是数据的两倍 复制。这不是很有效。另请注意,更改值 function2中的struct不会影响function1中的struct,它们 是内存中的不同数据。

请考虑以下代码:

struct some_struct {
    int an_int;
    char a_char[1234];
};

void function1(void)
{
    struct some_struct *s = malloc(sizeof(struct some_struct));
    function2(s);
    free(s);
}

void function2(struct some_struct *s)
{
    //do something with some_struct s
}

some_struct数据将放在堆而不是堆栈上。只要 指向此数据的指针将放在函数1的堆栈中,复制到 调用function2另一个指针放在函数2的堆栈上。这是一个 比前面的例子更有效率。另外,请注意任何变化 由function2生成的struct中的数据现在将影响struct中的结构 function1,它们与内存中的数据相同。

这基本上是更高级编程语言的基础 如Objective-C构建和构建这些语言的好处 像这样。

答案 2 :(得分:1)

指针的好处和需要是它的行为就像一面镜子。它反映了它所指向的内容。点可能非常有用的一个主要位置是在函数或方法之间共享数据。局部变量不保证每次函数返回时都保持它们的值,并且它们只在它们自己的函数内可见。但您仍然可能希望在函数或方法之间共享数据。您可以使用return,但仅适用于单个值。您也可以使用全局变量,但不能存储完整的数据,很快就会出现问题。所以我们需要一些可以在函数或方法之间共享数据的变量。指出我们的补救措施。您可以只创建数据并只传递指向该数据的内存地址(唯一ID)。使用此指针可以在任何函数或方法中访问和更改数据。在编写模块化代码方面,这是指针的最重要目的 - 在程序的许多不同位置共享数据。

答案 3 :(得分:0)

在这方面,C和Objective-C之间的主要区别在于Objective-C中的数组通常作为对象实现。 (数组总是作为Java中的对象实现,BTW和C ++有几个类似于NSArray的常见类。)

任何考虑过这个问题的人都会仔细地理解“裸”C类阵列是有问题的 - 处理起来很麻烦,而且常常是错误和混乱的根源。 (“一个数组'衰变'到一个指针” - 无论如何,这应该是什么意思,除了以一种反面的方式承认“是的,它令人困惑”??)

Objective-C中的分配在很大程度上有点令人困惑,因为它正在转换中。可以很容易地理解旧的手动引用计数方案(如果在实现中不那么容易处理),但ARC虽然更易于处理,但却难以真正理解,并且同时理解这两者更加困难。但是两者都比C更容易处理,其中“僵尸指针”几乎是给定的,因为缺少引用计数。 (C可能似乎更简单,但这只是因为你没有像使用Objective-C那样复杂的事情,因为很难控制它。)

答案 4 :(得分:0)

在引用堆上的某些内容时总是使用指针,有时,但通常不会在引用堆栈上的内容时使用。

由于Objective-C对象总是在堆上分配(除了Blocks,但这与此讨论正交),因此始终使用指向Objective-C对象的指针。 id和Class类型都是指针。

您不使用指针的地方是某些原始类型和简单结构。 NSPoint,NSRange,int,NSUInteger等...通常都是通过堆栈访问的,通常你不使用指针。