我有一个常量字符串值
std::string name_to_use = "";
我只需要在一个地方使用这个值,在上调用下面的函数
std::wstring foo (std::string &x) {...};
// ...
std::wstring result = foo (name_to_use);
我可以简单地不声明变量,而是在函数调用中使用字符串文字,但为了方便配置name_to_use
,我决定在文件开头声明。
现在,由于我并没有真正修改name_to_use
,我想为什么不使用#define
预处理指令,这样当主程序连续运行(显示GUI(时,我就不必将name_to_use作为常量存储在内存中的任何位置。
它运行良好,但后来我遇到了constexpr
。stackoverflow上的一位用户表示,使用它而不是#define
,因为它是一个更安全的选择。
然而,在这种情况下,constexpr std::string name_to_use
仍然会泄漏内存,对吧?因为它实际上并不是用值替换name_to_use
的出现,而是在编译时保留对它的引用(如果我没有错的话,这在这里不会给我带来任何好处?(。
如果将其#define
转换为""
,则在每次调用时都会有从c-string到std::string
的转换,这是非常低效的。不过,您可以(通常(将宏定义作为参数传递给编译器,这有助于自定义。即使在这种情况下,编写static constexpr std::string name_to_use
也是有意义的。
有了static constexpr std::string name_to_use = ...;
,转换问题就消失了(很可能在编译时完成(。不要指望编译器不进行优化——如果它是一个编译时字符串,那么可能会发生整个函数被优化掉的情况(但对象仍然存在,代码将遵守假设规则(。
要将两者结合起来,可以执行以下操作:
#ifdef NAME_TO_USE
constexpr const std::string = # NAME_TO_USE;
#else
constexpr const std::string = "";
#endif
此外,正如其他人所说,请考虑std::string_view
以避免分配。
用户说得很好,您确实理解得很好。
当宏在编译时仅替换自身时,使用constexpr
方法将分配一个常量。第一种方法的唯一好处是它是类型化的,并且在编译时可以使代码更安全
话虽如此,选择权在你。您想要一个在运行时不添加任何操作的非类型化宏,还是一个在解析时使用一点内存的类型化常量?