0

I have one header file where I am declaring variables like below :

//Constants.h
const std::string& binaryName = "ApplicationGateway";
const std::string& binaryMode = "Maintenance";

However when i include this file in multiple cpp files say first.cpp and second.cpp i get multiple definition error and i could not find the reasoning for same because my understanding is const variable have internal linkage.

So my question is does const reference don't have internal linkage and if not how we can have const reference in header file that need to be included in multiple cpp files.

PapaDiHatti
  • 1,841
  • 19
  • 26
  • Just curious - why do you want to store a reference to an unnamed string object instead of storing a string value? – Bo Persson May 02 '18 at 10:29
  • bcoz my understanding is string literals are stored in read only segment of memory and when we store by value it will get copied into that const string so just want to avoid copy – PapaDiHatti May 02 '18 at 11:14
  • Unfortunately this code will first create a copy and then store a reference to the copy. – Bo Persson May 02 '18 at 19:28
  • Can you provide some more details for better understanding and why it will first create a copy when we are directly creating a reference to string variable – PapaDiHatti May 03 '18 at 03:48
  • @Bo If you provide some insights why it will create a copy then it might be helpful – PapaDiHatti May 04 '18 at 04:32
  • The problem here is that `"Maintenance"` isn't of type `std::string` but of type `const char[12]`. So the compiler will have to convert that to a `std::string` object to have something that matches the reference type. That involves creating a new object. – Bo Persson May 04 '18 at 08:25
  • But in case of std::string binaryName = "ApplicationGateway" then compiler has to do copy two times one for converting and other for copying it to binaryName – PapaDiHatti May 04 '18 at 08:37
  • 1
    No, it doesn't do extra copies, the string object is created in place. Here is an old answer (to a totally different question) that shows [how little code it actually takes to create a std::string](https://stackoverflow.com/a/11639305/597607) – Bo Persson May 04 '18 at 08:46

2 Answers2

4

You should define them in Constants.cpp and mark them as extern in your header:

//Constants.cpp
const std::string& binaryName = "ApplicationGateway";
const std::string& binaryMode = "Maintenance";

//Constants.h
extern const std::string& binaryName;
extern const std::string& binaryMode;

Think of header files as being copied and pasted into everywhere you include said header file. That is why the compiler thinks you are declaring the variables over and over again, because to the compiler, the variables actually are. A quirk of this (though terrible design) is that if you were to keep it in your header, but only ever include it anywhere once, then your code should compile fine.

Benjamin James Drury
  • 2,353
  • 1
  • 14
  • 27
3

my understanding is const variable

This isn't a const variable, even though const does appear: const doesn't appear at the top level.

So my question is does const reference don't have internal linkage,

If you want internal linkage, you can specify that explicitly:

static const std::string& binaryName = "ApplicationGateway";
static const std::string& binaryMode = "Maintenance";

If you don't want internal linkage, as of C++17, you can define these as inline variables:

inline const std::string& binaryName = "ApplicationGateway";
inline const std::string& binaryMode = "Maintenance";

Like inline functions, these are allowed to be defined in multiple translation units, and you'll get the same string object in all.