objective-c 何时使用静态字符串与 #define
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2092005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use static string vs. #define
提问by mahboudz
I am a little confused as to when it's best to use:
我对什么时候最好使用有点困惑:
static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";
instead of
代替
#define AppQuitGracefullyKey @"AppQuitGracefully"
I've seen questions like this for C or C++, and I think what's different here is that this is specifically for Objective C, utilizing an object, and on a device like the iPhone, there may be stack, code space or memory issues that I don't yet grasp.
我见过类似 C 或 C++ 的问题,我认为这里的不同之处在于这是专门针对 Objective C,利用对象,而在像 iPhone 这样的设备上,可能存在堆栈、代码空间或内存问题我还没有掌握。
One usage would be:
一种用法是:
appQuitGracefully = [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey];
Or it is just a matter of style?
还是只是风格问题?
Thanks.
谢谢。
回答by cdespinosa
If you use a static, the compiler will embed exactly one copy of the string in your binary and just pass pointers to that string around, resulting in more compact binaries. If you use a #define, there will be a separate copy of the string stored in the source on each use. Constant string coalescing will handle many of the dups but you're making the linker work harder for no reason.
如果您使用静态,编译器将在您的二进制文件中嵌入该字符串的一个副本,并只传递指向该字符串的指针,从而生成更紧凑的二进制文件。如果您使用#define,则每次使用时都会有一个单独的字符串副本存储在源中。常量字符串合并将处理许多重复项,但您无缘无故地使链接器更努力地工作。
回答by kennytm
See "static const" vs "#define" vs "enum". The main advantage of staticis type safety.
请参阅“静态常量”与“#define”与“枚举”。的主要优点static是类型安全。
Other than that, the #defineapproach introduces a flexibility of inline string concatenation which cannot be done with static variables, e.g.
除此之外,该#define方法引入了使用静态变量无法完成的内联字符串连接的灵活性,例如
#define ROOT_PATH @"/System/Library/Frameworks"
[[NSBundle bundleWithPath:ROOT_PATH@"/UIKit.framework"] load];
but this is probably not a good style :).
但这可能不是一个好的风格:)。
回答by André Fratelli
I actually would recommend neither, you should use externinstead. Objective-c already defines FOUNDATION_EXPORTwhich is more portablethan extern, so a global NSStringinstance would look something like this:
我实际上不会推荐两者,你应该使用它extern。Objective-c 已经定义了FOUNDATION_EXPORT哪个比更便携extern,所以全局NSString实例看起来像这样:
.h
。H
FOUNDATION_EXPORT NSString * const AppQuitGracefullyKey;
.m
.m
NSString * const AppQuitGracefullyKey = @"AppQuitGracefully";
I usually put these in declaration files (such as MyProjectDecl.h) and import whenever I need.
我通常将它们放在声明文件(例如MyProjectDecl.h)中,并在需要时导入。
There are a few differences to these approaches:
这些方法有一些不同之处:
- #definehas several downsides, such as not being type safe. It is true that there are workarounds for that (such as
#define ((int)1)) but what's the point? And besides, there are debugging disadvantages to that approach. Compilers prefer constants. See thisdiscussion. - staticglobals are visible in the file they are declared.
- externmakes the variable visible to all files. That contrasts with static.
- #define有几个缺点,例如类型不安全。确实有解决方法(例如
#define ((int)1)),但有什么意义呢?此外,这种方法还有调试缺点。编译器更喜欢常量。看到这个讨论。 - 静态全局变量在它们声明的文件中可见。
- extern使变量对所有文件可见。这与静态形成对比。
Static and extern differ in visibility. It's also notable that neither of these approaches duplicates the string (not even #define) as the compiler uses String Interningto prevent that. In this NSHipster postthey show proof:
静态和外部的可见性不同。还值得注意的是,这些方法都不会复制字符串(甚至不会#define),因为编译器使用String Interning来防止这种情况发生。在这篇 NSHipster 帖子中,他们展示了证据:
NSString *a = @"Hello";
NSString *b = @"Hello";
BOOL wtf = (a == b); // YES
The operator ==returns YESonly if the two variables point at the same instance. And as you can see, it does.
仅当两个变量指向同一个实例时,运算符才==返回YES。正如你所看到的,它确实如此。
The conclusion is: use FOUNDATION_EXPORTfor global constants. It's debug friendly and will be visible allover your project.
结论是:FOUNDATION_EXPORT用于全局常量。它是调试友好的,并且在您的整个项目中都是可见的。
回答by Aleksa
After doing some search (thisquestion/answer among other things) I think it is important to say that anytime when you are using string literal @"AppQuitGracefully"constant string is created, and no matter how many times you use it it will point to the sameobject.
在做了一些搜索(这个问题/答案等等)之后,我认为重要的是要说当您使用字符串文字@"AppQuitGracefully"常量字符串时,无论您使用它多少次,它都会指向同一个对象。
So I think (and I apologize me if I'm wrong) that this sentence in above answer is wrong: If you use a #define, there will be a separate copy of the string stored in the source on each use.
所以我认为(如果我错了,我向我道歉)上面答案中的这句话是错误的: If you use a #define, there will be a separate copy of the string stored in the source on each use.
回答by Hitendra Solanki
USING #define :
使用 #define :
you can't debug the value of identifier
你不能调试标识符的值
work with #define and other macros is a job of Pre-Processor, When you hit Build/Run first it will preprocess the source code, it will work with all the macros(starting with symbol #),
使用#define 和其他宏是预处理器的工作,当您首先点击 Build/Run 时,它将预处理源代码,它将与所有宏一起使用(以符号 # 开头),
Suppose, you have created,
假设,你已经创建,
#define LanguageTypeEnglish @"en"
and used this at 2 places in your code.
并在代码中的 2 个地方使用了它。
NSString *language = LanguageTypeEnglish;
NSString *languageCode = LanguageTypeEnglish;
it will replace "LanguageTypeEnglish"with @"en", at all places.
So 2 copies of @"en"will be generated.
i.e
它将在所有地方用,替换“LanguageTypeEnglish”@"en"。因此@"en"将生成2 个副本。IE
NSString *language = @"en";
NSString *languageCode = @"en";
Remember, till this process, compiler is not in picture.
请记住,在此过程之前,编译器不在画面中。
After preprocessing all the macros, complier comes in picture, and it will get input code like this,
预处理完所有的宏后,编译器就出现了,它会得到这样的输入代码,
NSString *language = @"en";
NSString *languageCode = @"en";
and compile it.
并编译它。
USING static :
使用静态:
it respects scope and is type-safe. you can debug the value of identifier
它尊重范围并且是类型安全的。您可以调试标识符的值
During compilation process if compiler found,
在编译过程中如果编译器发现,
static NSString *LanguageTypeRussian = @"ru";
then it will check if the variable with the same name stored previously, if yes, it will only pass the pointer of that variable, if no, it will create that variable and pass it's pointer, next time onwards it will only pass the pointer of the same.
然后它会检查之前存储的同名变量是否存在,如果是,它只会传递该变量的指针,如果不是,它将创建该变量并传递它的指针,下次它只会传递该变量的指针相同。
So using static, only one copy of variable is generated within the scope.
所以使用静态,在作用域内只生成一份变量副本。
回答by Laurent Etiemble
I use staticwhen I need to export NSString symbols from a library or a framework. I use #definewhen I need a string in many places that I can change easily. Anyway, the compiler and the linker will take care of optimizations.
我static在需要从库或框架中导出 NSString 符号时使用。我用#define的时候,我需要在很多地方,我可以很容易地改变一个字符串。无论如何,编译器和链接器将负责优化。

