【问题标题】:Proper way to do const std::string in a header file?在头文件中执行 const std::string 的正确方法?
【发布时间】:2012-04-29 10:06:36
【问题描述】:

我正在编写一个 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);

所以,如果我错了,请纠正我,但是每次我使用 @987654329 调用上述 objectForKey 方法之一时,正在调用 std::string 的复制构造函数并且临时的 std::string 在堆栈上@,对吧?

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

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

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

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

【问题讨论】:

  • 在将 'const char* const' 替换为 'const std::string' 时要小心。静态对象的初始化顺序是未定义的,因此如果您在实际初始化自身之前使用 const 字符串初始化其他静态/常量对象,它可能会产生非常不愉快的后果。这不是 const char* const 的问题,它保证在任何执行开始之前就存在。这种情况也是调试的噩梦,因为代码看起来是正确的。

标签: c++ static constants stdstring


【解决方案1】:

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

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

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

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

(关于externconst 的原因,请参见this answer)。

在进程启动期间,您仍然需要支付所有全局变量的初始化价格。这在 101% 的情况下是可以接受的(给予或接受 2%),但您可以通过使用惰性对象来避免这种情况(我有 written about something similar here)。

【讨论】:

【解决方案2】:

您编写的代码非常好,至少因为您只有一个源文件中的#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";

【讨论】:

  • 那么,如果字符串是在 .cpp 文件中定义的,它们是什么时候实际实例化的?
  • @NatWeiss 它们将与所有其他全局变量一起实例化。
  • 变量定义多次的问题是否适用于“const char* const”?我很确定它没有,但我不明白为什么。是什么赋予了“const char* const”在包含其值的单个位置定义的特权(更好,IMO,尤其是在维护方面)?
  • 为了完整起见,如果您的 const 变量定义在命名空间下,您需要在源文件中重新打开它。
  • @CarolineBeltran constexpr char*表示 指针constexpr 但不是它所指向的。在 C++ 中,所有字符串文字都是 constant 字符数组,因此您必须有一个指向 const 数据的指针(如 char const*,又名 const char*,或者如果您希望指针为常量以及char const* const)。
猜你喜欢
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
相关资源
最近更新 更多