我正在编写一个Cocos2D-X游戏,其中玩家,敌人和其他角色将他们的属性存储在CCMutableDictionary
中,这有点像std::map<std::string, CCObject*>
的装饰者类。可以通过CCMutableDictionary::objectForKey(const std::string& key)
方法访问字典中的值。
现在,在我的许多.cpp文件中包含的头文件中,我有一些const char * const
字符串用于访问字典中的值,如下所示:
// in Constants.h
const char* const kAttributeX = "x";
const char* const kAttributeY = "y";
// in a .cpp file
CCObject* x = someDictionary->objectForKey(kAttributeX);
所以,如果我错了,请纠正我,但每次调用上述{{1}之一时,std::string
的复制构造函数都会被调用并且临时std::string
在堆栈中。使用objectForKey
的方法,对吧?
如果是这样的话,我觉得如果那些常量属性键已经是const char* const
个对象,那么它在运行时会更有效率。但是我如何以正确的方式做到这一点?
在Constants.h文件中定义它们,如下所示编译正常,但我觉得有些事情是不对的:
std::string
如果已经提出这个问题我很抱歉。我似乎无法在StackOverflow上找到我正在寻找的确切答案。
答案 0 :(得分:22)
您编写的代码完全没问题,至少只有#include
个{1}}文件只在一个源文件中。如果在多个源文件中使用头文件,则将多次定义相同的变量。在头文件中正确使用常量是将它们拆分为包含变量的声明的头(Constants.h
)和包含变量的源文件(Constants.h
)变量的定义:
标题文件:
Constants.cpp
源文件:
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern const std::string kAttributeX;
extern const std::string kAttributeY;
#endif
答案 1 :(得分:2)
您的第二个选项会导致在每个翻译单元(包含标题的cpp文件)中创建每个变量,这将略微增加代码大小以及添加一些运行时成本(在启动和销毁期间构造所有这些字符串)他们在流程终止期间)。
解决方案suggested by Joachim有效,但我发现分别声明和定义变量有点拖累。我个人讨厌重复自己,也不喜欢一遍又一遍地说同样的事情......
我不能在C ++中知道一个很好的解决方案,但是我所使用的编译器都支持__declspec( selectany )
之类的东西,这样你就可以在头文件中定义变量了只获得一个实例化的对象(而不是每个翻译单元一个)。
__declspec( selectany ) extern const std::string kAttributeX = "x";
(为什么extern
和const
都会看到this answer)。
您仍然有在流程启动期间支付所有全局变量的初始化价格的缺点。这可以在101%的时间内接受(给予或接受2%)但你可以通过使用惰性对象来避免这种情况(我written about something similar here)。