静态const与extern const有何不同?

cds*_*per 5 objective-c ios

在我的iOS/Objective C项目中,我经常使用带有API密钥的constants.h文件等.直到今天,我一直在声明我的常数static const:

static NSString * const kAPIKey = @"wembvkejrvb43789gvbiu2bvfake";
Run Code Online (Sandbox Code Playgroud)

这工作正常,但有一个不幸的缺点,我只能创建基元和NSString文字的常量.其他对象(如UIColor对象)不能存储在此常量中,因为它们无法使用静态文字语法进行初始化(我的理解,需要引用).

在阅读了一些C++文档后,我理解了一些事情:

  • static是不必要的,因为它const是隐式静态的.
  • 调用NSString * const x实际上是在x中声明一个常量和不可变的值.我无法更改值,但可以更改x指向的值.
  • 该const具有内部链接,意味着该值立即定义(在编译时可以推测).

这些结论是否正确?

怎样的extern const不同?我假设它们是外部链接的(因此是extern关键字).它们是在运行时定义的吗?我可以创建某种动态 extern const,可以使用类方法返回的值进行设置吗?

例如,我想创建一个包含UIColor值的全局范围常量.我想使用[UIColor colorWithRed:green:blue:alpha:]类方法构造此颜色值.这显然不适用于我一直在使用的内部链接常量(我假设因为它发生在编译时) - 但是可能使用外部常量,可能在+initialize方法中设置吗?

任何有关此行为细节的详细说明都会非常有用.

Cal*_*leb 9

静态是不必要的,因为const是隐式静态的.

不,那不是真的.

static 在文件范围内使用时(即在任何方法或函数之外)意味着该变量仅在该文件中可见.

extern 表示变量在某个其他文件中定义.

const 表示无法修改变量.

考虑字符串.通常,您将拥有一个实现文件(名称以.m结尾),它定义了一些常量字符串指针:

NSString *const SomeString = @"some string";
Run Code Online (Sandbox Code Playgroud)

您可能希望从其他文件中使用相同的常量.如果是这样,你可以在标题中添加一个声明(名称以.h结尾)文件,向编译器解释变量是在别处定义的:

extern NSString *const SomeString;
Run Code Online (Sandbox Code Playgroud)

这将允许您SomeString在任何导入头文件的文件中使用.另一方面,您可能会认为您绝对希望在实现文件外部使用常量.在这种情况下,您可以声明它static(在实现文件中):

static NSString *const SomeString = @"some string";
Run Code Online (Sandbox Code Playgroud)

这会阻止它从文件外部使用.

调用NSString * const x实际上是在x中声明一个常量和不可变的值.我无法更改值,但可以更改x指向的值.

对,它声明指针x是常量 - 你不能改变它.如果它实际上是一个NSString因为一个实例NSString不可变,你也无法改变它指向的值.

该const具有内部链接,意味着该值立即定义(在编译时可以推测).

我将采取第5个 - 我不确定编译器如何处理常量字符串.不过,我认为将其用作心理模型是安全的.在任何情况下,字符串都将在您的代码使用之前定义.