aarelovich
aarelovich

Reputation: 5586

Why is a globally define static variable being reset?

My code is very large, but I'll try to minimize it here as best as possible.

Basically I want to define a string that is modified in only one place (my main) and then be read in my entire program.

My defines.h is included everywhere so in there I defined.

static std::string MAINLOG = "RANDOMNES";

In my main function I do:

for (int i = 0; i < files.size(); i++){

    // Do stuff       

    prepDbugDir();  // This sets MAINLOG to "CORRECT_VALUE"

    std::cout << "Before " << MAINLOG << std::endl;

    // Call a class function whose includes include my defines.h

    std::cout << "After " << MAINLOG << std::endl;


}

And the print out of my file is

Before CORRECT_VALUE
RANDOMNESS
After CORRECT_VALUE

So my question is why and how can I get the value to be maintained inside my classes.

Upvotes: 6

Views: 2067

Answers (4)

Rob K
Rob K

Reputation: 8926

Because you put it in your defines.h file, which you then include in your .cpp files, each .cpp file gets its own instance of the string, visible only inside that .cpp file. static makes a variable only visible inside the .cpp where it's declared.

Change the static to extern in your defines.h, like this:

extern std::string MAINLOG;

Then in one and only one of your .cpp files, add this:

std::string MAINLOG = "RANDOMNES";

That will give you the behavior you expect, but global variables like this are a BAD idea.

Upvotes: 1

Violet Giraffe
Violet Giraffe

Reputation: 33627

Every translation unit (.c or .cpp file, basically) that includes defines.h will have its own copy of the variable.

I believe declaring the global extern in the header

extern std::string MAINLOG;

and then defining it as a non-static global variable in any one of the .c or .cpp files

std::string MAINLOG = "RANDOMNES";

will solve the problem. But it's poor coding style, IMO. The C++ way would be at least a singleton class.

I can't give meaningful names without knowing the context, but the idea is as follows:

mainlog.h

class Mainlog {
   Mainlog() = default; // Private default constructor

   static Mainlog& instance();

public:
   static const std::string& get() {
      return instance().value;
   }

   static void set(const std::string& newValue) {
      instance().value = newValue;
   }

private:
   std::string value {"RANDOMNESS"};
};

mainlog.cpp (don't put this in a header!)

Mainlog& Mainlog::instance() {
      static Mainlog mainlog;
      return mainlog;
   }

Upvotes: 6

molbdnilo
molbdnilo

Reputation: 66459

When you define a variable with static storage in a header, each translation gets its own unique variable by that name.

A simple fix, if you don't want to go the singleton way, is to declare

extern const std::string& MAINLOG;

in your header, and then the main file defines

std::string MAINLOG_INTERNAL = "RANDOMNESS";
const std::string& MAINLOG = MAINLOG_INTERNAL;

This will give you a writeable string that has a read-only "view" in the rest of the program.

Then you can

void prepDbugDir()
{
    MAINLOG_INTERNAL = "CORRECTNESS";
}

in the main file.

Upvotes: 1

Donghui Zhang
Donghui Zhang

Reputation: 1143

Here's what I would recommend.

In defines.h:

const std::string& mainlog();

In main.cpp:

const std::string& mainlog() {
  static std::string MAINLOG = "CORRECT_VALUE";
  return MAINLOG;
}

Upvotes: 2

Related Questions