1

If I have a string variable in a header file which will be used across different files and translation units, should I store it in a constexpr const char* or const std::string?

Here is an example:

// config.h

constexpr const char* string_a = "stringA"; // <--should i declare it like this?

const std::string string_b = "stringB";     // <--or like this?
// a.h

#include "config.h"

class A{
public:
    A();
};

// a.cpp

#include "a.h"

A::A(){
    cout << string_a << endl;
}
// b.h

#include "config.h"

class B{
public:
    B();
};

// b.cpp

#include "b.h"

B::B(){
    cout << string_b << endl;
}
// main.cpp

#include "a.h"
#include "b.h"

int main(){
    A a;
    B b;
    cout << string_a << endl;
    cout << string_b << endl;
    return 0;
}

I have read from books that it is recommended to always use string instead of char*, but I have also heard that constexpr is initialized in compile time which is quite good.

Komgcn
  • 323
  • 2
  • 12
  • 3
    Even if initialization is done at runtime, initialization of global variables (which really should be avoided) is done only once. The possible performance cost of initializing a `std::string` object is negligible. So use a `std::string` object, it will make life much easier for all kinds of string handling needed. – Some programmer dude Jun 19 '23 at 03:38
  • As you observed, `const char *` can be `constexpr`, while a string normally cannot. That may be important when you use it as a building block for other, more costly expressions which you would really like to have evaluated at compile time. – Peter - Reinstate Monica Jun 19 '23 at 07:08
  • There is a third choice which is better than either of yours: `const char string_a[]`. Saves you from all overheads. – user207421 Jun 19 '23 at 10:07
  • @user207421 do you mean I declare like constexpr const char string_a[7] = "stringA"; ? What is the difference between using array and pointer except for declaring initial size? I mean when the array is passed to a function, it will be converted to pointer anyway right? – Komgcn Jun 20 '23 at 08:00
  • That's correct. The difference is that a pointer costs the space for the pointer. If you declare as an array, the name `string_a` refers directly to the address of the string literal, rather than being another data item that contains that address. – user207421 Jun 20 '23 at 08:03

3 Answers3

1

Any time you consider making a tradeoff between speed vs. readability/maintainability, it is vital to profile your code to determine whether or not you see a non-negligible speed increase.

For your case, it is unlikely that constexpr will provide a significant speed increase. The significant downside is that you will have to manage the memory in the const char*, and you will lose access to std::string's convenient features.

Harry Williams
  • 310
  • 3
  • 11
0

There is no definitive answer to the question without knowing the specific context.

In many situations, it will not matter to the result which one you choose, and thus you should go for the one which fits the code base you are working with (i.e. think of code clarity and let the compiler worry about optimizing).

If you need to apply functions offered by the std::string class, then creating the std::string may be a good idea.

On the other hand, if you are coding for an environment with limited resources, e.g. an embedded application with a small amount of RAM and the program stored in non-volatile memory, it may be important that the the compiler is able to construct it at compile time. You would have to make the experiment, but this would certainly work with the const char *, but not so certainly with the std::string (though compilers get better all the time, so this may change).

Whether or not the compiler would be able to construct the variable at compile time also impacts whether or not it is a good idea to define the string in a header file at all. This is a question of its own, see Define constant variables in C++ header.

Finally, the const char * would be preferable if you need to access the string from code modules not written in C++, e.g. a plain C module.

nielsen
  • 5,641
  • 10
  • 27
0

It depends on the usage , for example if down the line you want to use the const char* as std::string in some functionality then it will have the overhead of creating the std::string out of const char*. But i would still move away from const char* and use std::string_view which you can constexpr but has the ability to tranform into const char* or std::string and vice-versa. Just be careful about the life time of object from which std::string_view is constructed. Here its not the problem as its gloabl.

Yusuf Khan
  • 409
  • 3
  • 9