次の比較は両方ともtrueと評価されます。
1)
@"foo" == @"foo";
2)
NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
myString1 == myString2;
ただし、NSString等式演算子を使用して2つのを比較できない場合[myString1 isEqualToString:myString2]があり、代わりに必要になります。誰かがこれに光を当てることができますか?
回答:
==動作する理由は、ポインタの比較のためです。を使用して定数NSStringを定義する@""と、コンパイラは参照を一意化します。コード内の他の場所で同じ定数が定義されている場合、それらはすべてメモリ内の同じ実際の場所を指します。
NSStringインスタンスを比較するときは、次のisEqualToString:方法を使用する必要があります。
NSString *myString1 = @"foo";
NSString *myString2 = @"foo";
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
NSLog(@"%d", (myString2 == myString3)) //0
NSLog(@"%d", (myString1 == myString2)); //1
NSLog(@"%d", [myString1 isEqualToString:myString2]); //1
NSLog(@"%d", [myString1 isEqualToString:myString3]); //1
[myString3 release];
編集:
NSString *myString3 = [[NSString alloc] initWithString:@"foo"];
// this is same with @"foo"
initWithString:これ以上新しい参照を作成しません。必要initWithFormatになります、
NSString *myString3 = [[NSString alloc] initWithFormat:@"foo"];
isEqual:実際には完全な文字列比較を行いisEqualToString、NSObjectプロトコルリファレンスとNSStringクラスリファレンスが(それぞれ)明示的に指定しているためと同じ結果を返します: "2つのオブジェクトが(によって-isEqual:)等しい場合、それらは同じでなければなりませんハッシュ値」および「2つの文字列オブジェクトが等しい場合(isEqualToString:メソッドによって決定される場合)、それらは同じハッシュ値を持っている必要があります。」
等価演算子==は、ポインタアドレスのみを比較します。リテラル@""構文を使用して2つの同一の文字列を作成すると、コンパイラはそれらが等しいことを検出し、データを1回だけ格納します。したがって、2つのポインターは同じ場所を指します。ただし、他の方法で作成された文字列には、同じデータが含まれていても、異なるメモリ位置に格納されている場合があります。したがって、文字列を比較するときは常に使用する必要がありisEqual:ます。
isEqual:とはisEqualToString:常に同じ値を返しますが、isEqualToString:より高速であることに注意してください。
isEqualToString、渡されたパラメータがnil。の場合、:は例外を引き起こすことに注意してください。したがって、nil文字列と比較する可能性がある場合は、最初にnilチェックを実行するか、isEqual:
==メモリ内の場所を比較します。ptr == ptr2両方が同じメモリ位置を指している場合。コンパイラはたまたま同一の文字列定数に対して1つの実際の文字列を使用するため、これは文字列定数で機能します。それはないでしょう、あなたが同じ内容の変数を持っている場合、彼らは別のメモリ位置を指しますので、動作します。isEqualToStringそのような場合に使用してください。
Cocoaでは、文字列はNSStringのisEqualToString:メソッドを使用して比較されます。
コンパイラは2つの文字列リテラルをマージして1つのオブジェクトを指すのに十分穏やかであるため、ポインタ比較はこの場合に機能します。2つの同一の文字列が1つのNSStringインスタンスを共有するという保証はありません。
NSString同じコンテンツを持つ2つの異なるインスタンスを作成するコードを簡単に記述できます:[NSMutableString string] != [NSMutableString string]
==機能が保証されます。ただし、1つのNSStringを削除し、値を割り当ててから、このように別のNSStringを削除NSString stringWithFormat:すると、実際には2つの異なる文字列が取得==されて失敗します。2つのNSString(NSMutableStringではない)インスタンスが1つのNSStringインスタンスを共有するという保証はないとおっしゃいましたが、共有できるように、その主張の証拠があるかどうかを尋ねました。
文字列比較の代理としてのアドレス比較がどのように機能するかを示す例:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *s1 = @"foo";
NSString *s2 = @"foo";
NSString *s3 = [[[NSString alloc] initWithString:@"foo"] autorelease];
NSMutableString *s4 = [NSMutableString stringWithString:@"foobar"];
[s4 replaceOccurrencesOfString:@"bar"
withString:@""
options:NSLiteralSearch
range:NSMakeRange(0, [s4 length])];
NSLog(@"s1 = %p\n", s1);
NSLog(@"s2 = %p\n", s2);
NSLog(@"s3 = %p\n", s3);
NSLog(@"s4 = %p\n", s4); // distinct from s1
NSLog(@"%i", [s1 isEqualToString:s4]); // 1
[pool release];
この例を確認してください。
NSString *myString1 = @"foo";
NSMutableString *myString2 = [[NSMutableString stringWithString:@"fo"] stringByAppendingString: @"o"];
NSLog(@"isEquality: %@", ([myString1 isEqual:myString2]?@"+":@"-")); //YES
NSLog(@"isEqualToStringity: %@", ([myString1 isEqualToString:myString2]?@"+":@"-")); //YES
NSLog(@"==ity: %@", ((myString1 == myString2)?@"+":@"-")); // NO
したがって、コンパイラーはisEqualToStringメソッドを使用してNSStringおよび逆参照ポインターのisEqualsを処理する可能性がありますが、そうする必要はありませんでした。ご覧のとおり、ポインタは異なります。
NSString *str1=[NSString stringWithFormat:@"hello1"];
NSString *str2=[NSString stringWithFormat:@"hello1"];
NSString *str3 = [[NSString alloc] initWithString:@"hello1"];
// == compares the pointer but in our example we are taking same string value to different object using @ so it will point to same address so output will be TRUE condition
if (str1==str2) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// == compares the pointer but in our example we are taking same string value to different object but we have allocated different string so both object will pount to different address so output will be FALSE condition
if (str1==str3) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// compare:= compares the values of objects so output will be TRUE condition
if ([str1 compare:str3]== NSOrderedSame) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// isEqual compares the values of objects so output will be TRUE condition
if ([str1 isEqual:str2]) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// isEqual compares the values of objects so output will be TRUE condition
if ([str1 isEqual:str3]) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// isEqualToString compares the values of objects so output will be TRUE condition
if ([str1 isEqualToString:str2]) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// isEqualToString compares the values of objects so output will be TRUE condition
if ([str1 isEqualToString:str3]) {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
// == compares the pointers since we have initialized the same value to first object so the pointer be be same for same value so output will be TRUE condition
if (str1==@"hello1") {
NSLog(@"Both String are equal");
}
else{
NSLog(@"Both String not are equal");
}
myString3定数へのポインタも作成する"foo"ため、通常、これら3つの変数はすべて同じメモリ位置を指します。これは、gccとclangの両方に当てはまります(デフォルトのオプションを使用)。これをコンパイルしてみてください:gist.github.com/578568