Program Tip

문자열 상수와 문자열 리터럴의 차이점은 무엇입니까?

programtip 2020. 12. 8. 19:51
반응형

문자열 상수와 문자열 리터럴의 차이점은 무엇입니까?


나는 Objective-C와 Cocoa를 배우고 있으며 다음과 같은 진술을 보았습니다.

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

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


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

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

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

// MyExample.h - declaration, other code references this
extern NSString * const MyExampleNotification;

// MyExample.m - definition, compiled for other code to reference
NSString * const MyExampleNotification = @"MyExampleNotification";

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

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

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


일부 정의

리터럴 정의상 불변의 값이다. 예를 들면 : 10
상수는 읽기 전용 변수 또는 포인터이다. 예를 들면 : const int age = 10;
문자열 리터럴 과 같은 표현이다 @"". 컴파일러는이를 NSString. 문자열 상수 에 대한 읽기 전용 포인터이다 . 예 :
NSStringNSString *const name = @"John";

마지막 줄에 대한 몇 가지 의견 :

  • 그것은 상수 객체가 아니라 상수 포인터입니다 1 . objc_sendMsg2 는 객체를 const. 불변 객체를 원한다면 객체 내부에 불변성을 코딩해야합니다 3 .
  • 모든 @""표현은 실제로 불변입니다. 그것들은 컴파일 타임에 4 개의 인스턴스 로 대체 NSConstantString되는데, 이것은 NSString고정 된 메모리 레이아웃 5가진 특수 서브 클래스입니다 . 이것은 또한 NSString컴파일 타임 6 에서 초기화 될 수있는 유일한 객체 인 이유를 설명합니다 .

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

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

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

3 예제 : in const NSMutableArray *array = [NSMutableArray new]; [array removeAllObjects];const는 마지막 문장을 막지 않습니다.

4 식을 다시 작성하는 LLVM 코드 RewriteModernObjC::RewriteObjCStringLiteral는 RewriteModernObjC.cpp에 있습니다.

5NSConstantString 정의 를 보려면 Xcode에서 cmd를 누른 채 클릭합니다.

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


견적으로 돌아 가기

Cocoa 프레임 워크는 문자열 리터럴이 아닌 전역 문자열 상수가 딕셔너리 키, 알림 및 예외 이름, 문자열을받는 일부 메소드 매개 변수에 사용되기를 기대합니다. 선택할 수있는 경우 항상 문자열 리터럴보다 문자열 상수를 선호해야합니다. 문자열 상수를 사용하면 컴파일러의 도움을 받아 맞춤법을 검사하고 런타임 오류를 방지 할 수 있습니다.

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

// string literal
[dic objectForKey:@"a"];

// string constant
NSString *const a = @"a";
[dic objectForKey:a];

In the second case I'm using keys with const pointers, so instead [a isEqualToString:b], I can do (a==b). The implementation of isEqualToString: compares the hash and then runs the C function strcmp, so it is slower than comparing the pointers directly. Which is why constant strings are better: they are faster to compare and less prone to errors.

If you also want your constant string to be global, do it like this:

// header
extern NSString *const name;
// implementation
NSString *const name = @"john";

Let's use C++, since my Objective C is totally non-existent.

If you stash a string into a constant variable:

const std::string mystring = "my string";

Now when you call methods, you use my_string, you're using a string constant:

someMethod(mystring);

Or, you can call those methods with the string literal directly:

someMethod("my string");

The reason, presumably, that they encourage you to use string constants is because Objective C doesn't do "interning"; that is, when you use the same string literal in several places, it's actually a different pointer pointing to a separate copy of the string.

For dictionary keys, this makes a huge difference, because if I can see the two pointers are pointing to the same thing, that's much cheaper than having to do a whole string comparison to make sure the strings have equal value.

Edit: Mike, in C# strings are immutable, and literal strings with identical values all end pointing at the same string value. I imagine that's true for other languages as well that have immutable strings. In Ruby, which has mutable strings, they offer a new data-type: symbols ("foo" vs. :foo, where the former is a mutable string, and the latter is an immutable identifier often used for Hash keys).

참고URL : https://stackoverflow.com/questions/25746/whats-the-difference-between-a-string-constant-and-a-string-literal

반응형