15

我正在编写一个 Cocos2D-X 游戏,其中玩家、敌人和其他角色将他们的属性存储在 aCCMutableDictionary中,这在某种程度上是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);

所以,如果我错了,请纠正我,但是每次我使用 a 调用上述方法之一时,都会调用std::string' 的复制构造函数并且临时在堆栈上,对吗?std::stringobjectForKeyconst char* const

如果是这样,我觉得如果这些常量属性键已经是std::string对象,那么在运行时会更有效。但是我该如何以正确的方式做到这一点?

像下面这样在 Constants.h 文件中定义它们可以很好地编译,但我觉得有些事情是不对的:

// in Constants.h
const std::string kAttributeX = "x";
const std::string kAttributeY = "y";

如果这个问题已经被问到,我很抱歉。我似乎无法在 StackOverflow 上找到我正在寻找的确切答案。

4

2 回答 2

29

您编写的代码非常好,至少因为您只有一个源文件中#include的文件。Constants.h如果您在多个源文件中使用头文件,您将多次定义相同的变量。头文件中常量的正确使用是将它们拆分为Constants.h包含变量声明Constants.cpp的头文件 ( ) 和包含变量定义的源文件 ( ) :

头文件:

#ifndef CONSTANTS_H
#define CONSTANTS_H

extern const std::string kAttributeX;
extern const std::string kAttributeY;

#endif

源文件:

const std::string kAttributeX = "x";
const std::string kAttributeY = "y";
于 2012-04-18T02:22:30.583 回答
3

您的第二个选项会导致在每个翻译单元(包含标头的 cpp 文件)中创建每个变量,这将略微增加代码大小并增加一些运行时成本(在启动期间构建所有这些字符串并在过程中破坏它们终止)。

Joachim 建议的解决方案有效,但我发现分别声明和定义变量有点麻烦。我个人讨厌重复自己,也不喜欢一遍又一遍地说同样的话……

我不知道在 C++ 中是否有一个好的解决方案,但是我使用过的编译器都支持类似的东西,__declspec( selectany )这样您就可以在头文件中定义变量并且只实例化一个对象(而不是每个翻译一个单元)。

__declspec( selectany ) extern const std::string kAttributeX = "x";

(为什么两者都externconst这个答案)。

您仍然有在进程启动期间支付所有全局变量的初始化价格的缺点。这在 101% 的情况下是可以接受的(给予或接受 2%),但您可以通过使用惰性对象来避免这种情况(我在这里写过类似的东西)。

于 2015-02-22T13:27:30.703 回答