jacek.ciach
jacek.ciach

Reputation: 1042

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

I have a method / function:

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 is only an example)

  1. static const will be initialized only once, but persists in memory until the process ends.
  2. const will be initialized every time foo() is run, but the memory (stack) is freed when the {} block ends.

On the other hand, the string "SELECT ... " has to be still hardcoded in the program code. And it's no matter if we use 1. or 2.

So which approach is better? Using static const std::string or only const std::string?

Or maybe there's no one answere, because it depends how I want to use foo() -- call it 1000 times per second (then I don't want to initialize a variable every time) or call it 1000 times per month (then I don't care).

(I've read Question Difference between static const char* and const char* and especially answer https://stackoverflow.com/a/2931146/945183, but they apply to const char*.)

Upvotes: 4

Views: 2865

Answers (4)

bobah
bobah

Reputation: 18864

Static non-primitive locals (const or not) do atomic read on every function call (initialization flag). They are thread safe (speaking of GCC) only when requested specifically via a compiler flag. The string strSQL constructed at run-time will be much more of a performance hit (because of heap allocation) than static initialization caused atomic read.

The fastest would be something like this:

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);
    ...
}

Whether you need to sacrifice readability for speed is another question.

Upvotes: 0

Sebastian Redl
Sebastian Redl

Reputation: 71999

Profile it. Chances are, the trip to the database so utterly dwarfs the initialization cost of the strings that it doesn't matter.

And as has been pointed out, local statics are not thread-safe on all compilers. They are in GCC, and C++11 requires them to be, but it took Microsoft until VS2013 to actually implement this.

Upvotes: 2

faraday
faraday

Reputation: 41

As I known "static" is not necessary in your case. 1) When you declare and define a const variable, compiler has a chance to replace all occurrences with the value you assigned, like following:

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

will become

int b = sqrt( 9 );

This behaves just like #define in C style. If this is what you want, then you already have it without "static".

2) As others told, static variables will remain existence even after foo() returns. I suppose this is not your objective

Upvotes: 0

waTeim
waTeim

Reputation: 9235

Well if a member variable, static const is safe so long as you don't intentionally defeat the const part by casting. But from your linked comments a local variable is different:

A local static variable is initialized the first time its definition is encountered, but not destructed when the function exits. So it keeps its value between invocations of the function.

To make this safe, gcc emits locking to protect the initialization but MS C++ does not as described here, so this can be either safe or not depending on the compiler and even if supposedly safe can have inimical side effects.

The tradeoff here seems to be efficiency versus maintainability. Is that extra little speed worth the possibility of introducing some subtle error. While researching this, I've come full circle on my opinion now, I'd say usually no. Especially since in this case it's a simple string initialization followed up by a lengthly database call.

Upvotes: 1

Related Questions