문제

나는 Objective-C와 Cocoa를 배우고 있으며 다음과 같은 진술을 발견했습니다. <인용구>

Cocoa 프레임 워크는 문자열 리터럴이 아닌 전역 문자열 상수가 사전 키, 알림 및 예외 이름, 문자열을받는 일부 메소드 매개 변수에 사용되기를 기대합니다.

저는 높은 수준의 언어로만 작업했기 때문에 문자열의 세부 사항을 그렇게 많이 고려할 필요가 없었습니다.문자열 상수와 문자열 리터럴의 차이점은 무엇입니까?

도움이 되었습니까?

해결책

Objective-C에서 @"foo" 구문은 NSString 불변 , 리터럴 인스턴스입니다. Mike가 가정하는 것처럼 문자열 리터럴에서 상수 문자열을 만들지 않습니다.

Objective-C 컴파일러는 일반적으로 컴파일 단위 내에서 인턴 리터럴 문자열을 실행 합니다. 즉, 동일한 리터럴 문자열을 여러 번 사용하여 통합하며 링커가 컴파일 단위에서 추가 인턴을 수행 할 수 있습니다. 단일 바이너리로 직접 연결됩니다. (Cocoa는 변경 가능한 문자열과 변경 불가능한 문자열을 구분하고 리터럴 문자열도 항상 변경 불가능하므로 간단하고 안전 할 수 있습니다.) 반면

상수 문자열은 일반적으로 다음과 같은 구문을 사용하여 선언되고 정의됩니다. 라코 디스

여기서 구문 연습의 요점은 여러 프레임 워크에서도 사용중인 해당 문자열의 인스턴스가 하나만 있는지 확인하여 문자열을 효율적으로 사용 할 수 있다는 것입니다. (공유 라이브러리) 같은 주소 공간에 있습니다. (const 키워드의 배치가 중요합니다. 포인터 자체가 일정 함을 보장합니다.)

메모리를 굽는 것은 8MB의 RAM이있는 25MHz 68030 워크 스테이션의 시대만큼 큰 문제는 아니지만 문자열을 비교하는 데 시간이 걸릴 수 있습니다. 동일한 대부분의 시간 문자열이 포인터와 동일한 도움이되도록합니다.

예를 들어 이름으로 개체의 알림을 구독하고 싶다고 가정 해 보겠습니다. 이름에 상수가 아닌 문자열을 사용하는 경우 알림을 게시하는 NSNotificationCenter는 관심있는 사람을 결정할 때 많은 바이트 단위 문자열 비교를 수행 할 수 있습니다. 비교되는 문자열이 동일한 포인터를 가지고 있기 때문에 이러한 비교의 대부분이 단락되면 큰 승리가 될 수 있습니다.

다른 팁

일부 정의

리터럴 은 정의에 따라 변경할 수없는 값입니다. 예 : 10
상수 는 읽기 전용 변수 또는 포인터입니다. 예 : const int age = 10;
문자열 리터럴 @""와 같은 표현식입니다. 컴파일러는 이것을 NSString의 인스턴스로 대체합니다.
문자열 상수 NSString에 대한 읽기 전용 포인터입니다. 예 : NSString *const name = @"John";

마지막 줄의 몇 가지 설명 :

  • 상수 개체가 아닌 상수 포인터입니다 1 . objc_sendMsg 2 const로 객체를 한정하더라도 상관하지 않습니다. 불변 객체를 원하면 객체 3 내에 불변성을 코딩해야합니다.
  • 모든 유전자 태그 코드 표현은 실제로 변경이 불가능합니다. 컴파일 타임에 4 는 고정 메모리 레이아웃 5 을 사용하는 @""의 특수 하위 클래스 인 NSConstantString의 인스턴스로 대체됩니다. 이것은 또한 NSString가 컴파일 타임에 초기화 될 수있는 유일한 객체 인 이유를 설명합니다 6 .

    상수 문자열 NSString에 해당하는 const NSString* name = @"John";입니다. 여기서 구문과 프로그래머 의도는 모두 잘못되었습니다. NSString const* name= @"John";는 무시되고 const <object> 인스턴스 (NSString)는 이미 변경 불가능했습니다.

    1 키워드 NSConstantString는 바로 왼쪽에있는 모든 항목에 적용됩니다. 왼쪽에 아무것도 없으면 바로 오른쪽에있는 모든 항목에 적용됩니다.

    2 런타임이 Objective-C의 모든 메시지를 보내는 데 사용하는 함수이므로 개체의 상태를 변경하는 데 사용할 수 있습니다.

    3 예 : const에서 const는 마지막 문장을 막지 않습니다.

    4 식을 다시 작성하는 LLVM 코드는 RewriteModernObjC.cpp의 const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects];입니다.

    5 RewriteModernObjC::RewriteObjCStringLiteral 정의를 보려면 Xcode에서 cmd를 누른 상태에서 클릭하십시오.

    6 다른 클래스에 대한 컴파일 시간 상수를 만드는 것은 쉽지만 컴파일러가 특수 하위 클래스를 사용해야합니다. 이로 인해 이전 Objective-C 버전과의 호환성이 깨집니다.

    <시간>

    견적으로 돌아 가기 <인용구>

    Cocoa 프레임 워크는 글로벌 문자열 상수가 문자열 리터럴은 사전 키, 알림 및 예외 이름 및 문자열을받는 일부 메소드 매개 변수. 당신 항상 문자열 리터럴보다 문자열 상수를 선호해야합니다. 선택권이 있습니다. 문자열 상수를 사용하여 맞춤법을 검사하여 런타임 오류를 방지하는 컴파일러

    리터럴은 오류가 발생하기 쉽다고 말합니다. 그러나 그들은 또한 더 느리다고 말하지 않습니다. 비교 : 라코 디스

    두 번째 경우에는 const 포인터가있는 키를 사용하므로 NSConstantString 대신 [a isEqualToString:b]를 수행 할 수 있습니다. (a==b)의 구현은 해시를 비교 한 다음 C 함수 isEqualToString:를 실행하므로 포인터를 직접 비교하는 것보다 느립니다. 상수 문자열이 더 나은 이유는 비교 속도가 더 빠르며 오류 발생 가능성이 적습니다.

    상수 문자열도 전역이되도록하려면 다음과 같이하십시오. 라코 디스

오브젝티브 C가 완전히 존재하지 않기 때문에 C ++를 사용합시다.

문자열을 상수 변수에 숨기는 경우 : 라코 디스

이제 메소드를 호출 할 때 my_string을 사용하고 문자열 상수를 사용합니다. 라코 디스

또는 문자열 리터럴을 사용하여 이러한 메서드를 직접 호출 할 수 있습니다. 라코 디스

아마도 그들이 문자열 상수를 사용하도록 권장하는 이유는 Objective C가 "인터 닝"을하지 않기 때문입니다. 즉, 여러 위치에서 동일한 문자열 리터럴을 사용할 때 실제로는 별도의 문자열 복사본을 가리키는 다른 포인터입니다.

사전 키의 경우 두 포인터가 동일한 것을 가리키는 것을 볼 수 있다면 문자열이 동일한 값을 갖도록 전체 문자열 비교를 수행하는 것보다 훨씬 저렴합니다. p>

편집 : Mike, C # 문자열은 변경할 수 없으며 동일한 값을 가진 리터럴 문자열은 모두 동일한 문자열 값을 가리 킵니다. 불변의 문자열을 가진 다른 언어도 마찬가지라고 생각합니다. 변경 가능한 문자열이있는 Ruby에서는 기호 ( "foo"대 : foo, 전자는 변경 가능한 문자열이고 후자는 해시 키에 자주 사용되는 변경 불가능한 식별자)와 같은 새로운 데이터 유형을 제공합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top