NSString文字之间的区别

时间:2011-11-07 03:12:38

标签: objective-c cocoa nsstring

这两行之间有什么区别?

NSString * string = @"My String";
NSString * string = [[[NSString alloc] initWithString:@"MyString"] autorelease]

5 个答案:

答案 0 :(得分:23)

@“My String”是编译成二进制文件的文字字符串。加载后,它在内存中占有一席之地。第一行声明一个指向内存中该点的变量。

来自字符串编程指南:

  

在源代码中创建字符串对象的最简单方法是使用   Objective-C @“...”构造:

NSString *temp = @"/tmp/scratch"; 
  

注意,创建字符串时   以这种方式保持不变,除了7位之外,你应该避免使用任何东西   ASCII字符。这样的对象是在编译时创建的并且存在   整个程序执行期间。编译器生成这样的对象   每个模块唯一的常量,它们永远不会被释放,   虽然你可以保留和释放它们,就像你做任何其他对象一样。

第二行通过获取该文字字符串来分配字符串。请注意,@“My String”文字字符串都是相同的。为了证明这一点:

NSString *str = @"My String";
NSLog(@"%@ (%p)", str, str);

NSString *str2 = [[NSString alloc] initWithString:@"My String"];
NSLog(@"%@ (%p)", str2, str2);

NSString *copy = [str2 stringByAppendingString:@"2"];
NSLog(@"%@ (%p)", copy, copy);

输出相同的内存地址:

2011-11-07 07:11:26.172 Craplet[5433:707] My String (0x100002268)
2011-11-07 07:11:26.174 Craplet[5433:707] My String (0x100002268)
2011-11-07 07:11:26.174 Craplet[5433:707] My String2 (0x1003002a0)

告诉我们不仅前两个字符串是相同的内存地址,而且如果不更改代码,每次运行它时都是相同的内存地址。它与内存中的二进制偏移量相同。但是,不仅副本不同,而且每次运行它都会有所不同,因为它是在堆上分配的。

根据上面的doc ref,自动释放没有任何影响。您可以释放它们,但它们永远不会被释放。所以,它们是相同的,不是因为它们都是自动释放的字符串,而是它们都是常量而且发布被忽略。

答案 1 :(得分:6)

一个是文字字符串,它在执行应用程序的生命周期中持续存在。另一个 可能 是一个动态对象,只有在自动释放后才会持续存在。 (它也可能是一个文字字符串,如果系统决定以这种方式优化它 - 不能保证它不会。)

答案 2 :(得分:2)

bryanmac在答案中100%正确。我刚刚使用GHUnit添加了一个明确的示例。

NSString创作 - 文字与非文字。

显示以各种方式创建的字符串,如果它们是文字的,也不是非文字的。

- (void) test_stringCreation
{
    NSString *literalString = @"literalString";
    NSString *referenced = literalString;
    NSString *copy = [literalString copy];
    NSString *initWithString = [[NSString alloc] initWithString:literalString];
    NSString *initWithFormat = [[NSString alloc] initWithFormat:@"%@", literalString];

    // Testing that the memory addresses of referenced objects are the same.
    GHAssertEquals(literalString, @"literalString", @"literal");
    GHAssertEquals(referenced, @"literalString", @"literal");
    GHAssertEquals(copy, @"literalString", @"literal");
    GHAssertEquals(initWithString, @"literalString", @"literal");
    GHAssertNotEquals(initWithFormat, @"literalString",
                      @"nonliteral - referenced objects' memory addresses are \
                      different.");

    // Testing that the objects referenced are equal, i.e. isEqual: .
    GHAssertEqualObjects(literalString, @"literalString", nil);
    GHAssertEqualObjects(referenced, @"literalString", nil);
    GHAssertEqualObjects(copy, @"literalString", nil);
    GHAssertEqualObjects(initWithString, @"literalString", nil);
    GHAssertEqualObjects(initWithFormat, @"literalString", nil);

    // Testing that the strings referenced are the same, i.e. isEqualToString: .
    GHAssertEqualStrings(literalString, @"literalString", nil);
    GHAssertEqualStrings(referenced, @"literalString", nil);
    GHAssertEqualStrings(copy, @"literalString", nil);
    GHAssertEqualStrings(initWithString, @"literalString", nil);
    GHAssertEqualStrings(initWithFormat, @"literalString", nil);
}

答案 3 :(得分:1)

它们之间没有区别。在第一个示例中显示的字符串是一个自动释放的字符串。

答案 4 :(得分:0)

记住这个基本的东西: -

NSString *string = ...

这是指向对象的指针,"不是对象"!

因此,语句:NSString *string = @"Hello";@"Hello"对象的地址分配给指针字符串。

编译器将

@"Hello"解释为常量字符串,编译器本身为其分配内存。

同样,声明

NSObject *myObject = somethingElse;

将somethingElse的地址分配给指针myObject,并且somethingElse应该已经分配了广告初始化。

因此,声明:NSObject *myObject = [[NSObject alloc] init];分配并初始化NSObject对象,并将其地址分配给myObject