web-dev-qa-db-ja.com

目的C-値渡しと参照渡し

まず、この単純な質問でごめんなさい。しかし、私は何が起こっているのかを理解する必要があります。

出力はupper case string。しかし、それはUPPER CASE STRING

- (void)test
{
     NSString *stringVar = @"UPPER CASE STRING";
     [self changeString:stringVar];
     NSLog(@"value after changed : %@", stringVar);
}

- (void)changeString:(NSString*)string
{
     string = [string lowercaseString];
}

何が起こっているのか、それを修正するにはどうすればよいですか?

26

[string lowercaseString]呼び出しは、ローカル変数NSStringに割り当てるnewstringオブジェクトを作成します。これは、stringVar関数の外のchangeStringの値を変更しません。ポインタ自体は値で渡されます。

あなたが望むことをする1つの方法は、ポインターをポインターに渡すことです:

-(void) test
{
     NSString *stringVar = @"UPPER CASE STRING";
     [self changeString:&stringVar];
     NSLog(@"value after changed : %@", stringVar);
}

-(void) changeString:(NSString**)string
{
     *string = [*string lowercaseString];
}
58
Greg Hewgill

[NSString lowerCaseString]method への参照を見ると、小文字の文字を含む新しい文字列が返されていることがわかります。

レシーバの小文字表現を返します。

- (NSString *)lowercaseString

コードが行うことは、入力文字列への参照をlowercaseString呼び出しの出力で上書きするだけで、効果はありません。この問題を解決する最良の方法は、自分で値を返すことです。これにより、メソッドが理解しやすくなります。

-(void) test
{
     NSString *stringVar = @"UPPER CASE STRING";
     stringVar = [self changeString:stringVar];
     NSLog(@"value after changed : %@", stringVar);
}

-(NSString *) changeString:(NSString*)string
{
     string = [string lowercaseString];
     return string;
}

NSStringは不変であることを理解する必要があるため、参照を再割り当てする以外に、文字列の内容を変更する方法はありません。ただし、代わりにNSMutableStringを使用することもできます。

7
trojanfoe

私は上記の与えられた問題を参照し、あなたが間違いを手伝っています。

- (void)test
{
     NSString *stringVar = @"UPPER CASE STRING";
     //StringVar is a pointer to integer class.let us assume the address the stringVar be 0x50 and the value it has be 0x100
     //So 0x100 has the string 

     [self changeString:stringVar];
     //above we are calling the method to lowercase and argument is stringVar
     //As the method is called we pass 0x100 in the argument as this is the memory where the value is kept

     NSLog(@"value after changed : %@", stringVar);
    //Our StringVar still points to 0x100 where the value is in upperString
}

- (void)changeString:(NSString*)string
{
     string = [string lowercaseString];
    // Now operation performed on string returns a new value on suppose location 0x200
   //String parameter passed in argument is assigned the new value.But we never pass values as we pass only location under the hood
   //New parameter passed now points to new memory location 0x200

}

---------------------------------------------------------------------------------
With the new solution
-(void) test
{
     NSString *stringVar = @"UPPER CASE STRING";
     //let 0x50 be stringVar memorylocation pointing to 0x100 with above value
     [self changeString:&stringVar];
     //0x50 is passed in argument
     NSLog(@"value after changed : %@", stringVar);
     //On new location stored in address of stringVar it points to new string value
}

-(void) changeString:(NSString**)string
{
     *string = [*string lowercaseString];
     //0x200 is new memory location received.*string gives the 0x100 location and hence the value
   //LHS is assigned to new location .On LHS you find *string which will be assigned 0x200
   //As string with location 0x50 is value 0x200 which will make it to point new      location where lowercase string exist
}
1

-(void) changeString:(NSString*)stringの文字列はローカル変数です。値を返すようにメソッドを変更してください:

-(void) test
{
     NSString *stringVar = @"UPPER CASE STRING";
     stringVar =[self changeString:stringVar];
     NSLog(@"value after changed : %@", stringVar);
}
-(NSString *) changeString:(NSString*)string
{
    return [string lowercaseString];
}
0
mas'an

stringはローカル変数(不変のNSStringへのポインター)であり、ローカル関数でstringpointsが何を指しているかを変更しているだけですが、その値を返すと、その値は破棄されます。

文字列をパラメータとして渡し、関数から小文字の文字列を返すだけでよいでしょう。

0