在方法/函数中使用"static const std::string"还是只使用"cons

Is it better to use `static const std::string` or just `const std::string` in a method/function?

本文关键字:quot string cons std static 方法 函数 const      更新时间:2023-10-16

我有一个方法/函数:

void foo() {
static const std::string strSQLQuery = "SELECT ... ";
// or maybe
const std::string strSQLQuery = "SELECT ... "; 
// some operations on strSQLQuery
// i.e. concatenating with WHERE, etc.:
const std::string strSQL = strSQLQuery + strWHERE;
doSthOnDataBase(strSQL);
}

(SQL只是一个示例)

  1. static const将仅初始化一次,但会保留在内存中,直到进程结束。
  2. 每次运行foo()时都会初始化const,但当{}块结束时,内存(堆栈)会释放。

另一方面,字符串"SELECT ... "仍必须在程序代码中硬编码。而且我们是否使用 1 都没关系。或 2.

那么哪种方法更好呢?使用static const std::string还是仅使用const std::string

或者也许没有一个答案,因为这取决于我想如何使用foo()- 每秒调用它 1000 次(然后我不想每次都初始化变量)或每月调用它 1000 次(然后我不在乎)。

(我已经阅读了静态常量字符*和常量字符*之间的问题区别,尤其是答案 https://stackoverflow.com/a/2931146/945183,但它们适用于const char*

剖析它。很有可能,数据库之旅使字符串的初始化成本相形见绌,以至于无关紧要。

正如已经指出的,局部静态并不是所有编译器上的线程安全的。它们在 GCC 中,C++11 要求它们在 GCC 中,但直到 VS2013 才Microsoft才真正实现这一点。

好吧,如果是一个成员变量,静态 const 是安全的,只要你不故意通过强制转换来破坏 const 部分。 但是从您链接的注释来看,局部变量是不同的:

局部静态变量在第一次遇到其定义时初始化,但在函数退出时不会销毁。因此,它在函数调用之间保持其值。

为了保证安全,gcc 发出锁定来保护初始化,但 MS C++ 不像这里描述的那样,所以这可能是安全的,也可能是不安全的,这取决于编译器,即使被认为是安全的也可能会产生有害的副作用。

这里的权衡似乎是效率与可维护性。 额外的小速度是否值得引入一些微妙的错误。 在研究这个问题时,我现在对我的观点已经完全了解了一圈,我通常会说不。 特别是因为在这种情况下,它是一个简单的字符串初始化,然后是冗长的数据库调用。

众所周知,在您的情况下,"静态"不是必需的。 1) 当您声明并定义一个 const 变量时,编译器有机会将所有出现项替换为您分配的值,如下所示:

const int var = 9;
int b = sqrt( var );

将成为

int b = sqrt( 9 );

这就像 C 样式中的 #define 一样。如果这是您想要的,那么您已经拥有了它,而无需"静态"。

2) 正如其他人所说,即使在 foo() 返回后,静态变量仍将存在。我想这不是你的目标

静态非原始局部变量(无论是否const)在每次函数调用(初始化标志)上都进行原子读取。它们仅在通过编译器标志特别请求时才是线程安全的(说到 GCC)。在运行时构造的字符串strSQL比静态初始化引起的原子读取对性能的影响要大得多(因为堆分配)。

最快的是这样的:

void call(std::string const& where) {
static char prefix[] = "SELECT ...";
std::string strSQL;
strSQL.reserve(sizeof(prefix)/sizeof(char) + strWHERE.size()); 
strSQL.append(prefix, sizeof(prefix)/sizeof(char)).append(strWHERE);
...
}

您是否需要为了速度而牺牲可读性是另一个问题。