1

I am working with a class whose constructor declares and initializes a static const variable in the implementation. This is not a data member of the class. I understand the use of const in this context, but what is gained by using static?

I understand that the static const global constants are shared by all instances of the class. Does that also happen with the variable inside the constructor?

Also, why would this not be defined at the Global scope, like the other two? That's where I would normally define my constants.

Example Code:

#includes...

static const int GLOBAL_CONST1 = 100;
static const double GLOBAL_CONST2 = 1.0;

SomeClass::SomeClass()
   :
      theDataMember1        (),
      theDataMember2        (),
      ...
{

   static const double SOME_VAR = 0.01; // Why not declare this globally?
   theDataMember1 = SomeIncludedClass(SOME_VAR);

}
KyleEnglish
  • 35
  • 1
  • 1
  • 9
  • *Why not declare this globally* because in most cases global variables are evil – NathanOliver Mar 09 '16 at 17:10
  • `const` values often get substituted by the optimizer, and the variable itself goes away completely. – Ben Voigt Mar 09 '16 at 17:11
  • This looks like an attempt at self-documenting code by naming the constant but constricting the scope to the minimum required. Seems a little overzealous to me and could have just used a comment if it's only used in that one line, but there's nothing wrong with it. – Kurt Stutsman Mar 09 '16 at 17:15
  • There's no real gain in having a static const variable within a function. Might you explain why would you want to do this? – Poriferous Mar 09 '16 at 17:25
  • Hi @Poriferous, this is legacy code I'm trying to read through and understand. I just don't see any reason for making it static except to confuse me. – KyleEnglish Mar 09 '16 at 17:31
  • @NathanOliver agreed. But never-the-less there they are. – KyleEnglish Mar 09 '16 at 17:33
  • @KyleEnglish FWIW, to be pedantic, the other two aren't "global" scope; they're translation unit scope so can only be accessed from within the same file as the SomeClass constructor (assuming you're showing a .cpp file). – cosimo193 May 06 '21 at 09:15

6 Answers6

11

Static Variable gets constructed only once no matter how many times the function is called.

So in case your defining constants inside a function and the function is called multiple times, then to reduce the cost of constructing this object every time the function is called you would make it a static variable (Mainly useful when its a constant, Else you may end up changing this value and it soon gets messed up).

For your second question, This is because you don't want others to be able to access the value of variable "SOME_VAR". Giving a global scope means any one can access it.

This link provides a good example about how local static is sometimes useful than global static variables.

Community
  • 1
  • 1
Kishore Bandi
  • 5,537
  • 2
  • 31
  • 52
  • 5
    The keyword `const` in `static const` allows the compiler to perform other optimizations, such as treating the *variable* as a numeric constant and placing directly into the code segment of the executable. Or the compiler can place the variable into a "constant" memory section (such as Flash or ROM). – Thomas Matthews Mar 09 '16 at 18:41
  • @ThomasMatthews I didn't know this. Thanks for the info :) – Kishore Bandi Mar 10 '16 at 06:44
3

When the constant is used only in one single function it can make sense to declare it only in the scope of the function it is used in. Why the static is used here does not really make sense to me, because it will be the same in all instances of the class anyway since it is a compile time constant.

But: You can also initialize the constant from parameters computed at runtime. In that case the value of the constant will be defined by the first instance of the class:

class A {
public:
    A(int param)
    {
        static const int MY_CONST = param;
        cerr << "param: " << param << "  const: " << MY_CONST << endl;
    };
};

int main()
{
    A a1(1);
    A a2(2);
    return 0;
}

output:

param: 1  const: 1
param: 2  const: 1
K-os
  • 196
  • 4
1

// Why not declare this globally?

By only seeing an abridged code fragment, we can only guess. It's typically good practice to put your variables in the narrowest scope possible. After all, everything could be global - we just choose to encapsulate things.

Perhaps the global constants are actually used in a lot of places, whereas the local constant is only used in that local function.

but what is gained by using static?

Probably just consistency. If you're just used to typing your constant values like:

static const T val = ddd;

everywhere, why change when you do it locally? There isn't an advantage or disadvantage of static for creating constant numbers.

Barry
  • 286,269
  • 29
  • 621
  • 977
0

static variables are literally static: they are allocated in same place as global variables. Plain local variables are allocated every time function is called on stack. If function is called n times recursively, there are n local variables. Static variable initialized only once. After it has been initialized, there is be only one instance of static variable. So static const local variable is used because of performance reasons.

Variables should have as narrow scope as possible to avoid unnecessary coupling. That's why this variable is local.

George Sovetov
  • 4,942
  • 5
  • 36
  • 57
  • 1
    "There is always one instance of static variable" - wrong. – SergeyA Mar 09 '16 at 17:19
  • 2
    @SergeyA You should explain why he's wrong or point to something so that he can learn why. – Kurt Stutsman Mar 09 '16 at 17:23
  • @SegeyA, I would like to know how I can have more than one static variable. Or do you mean that before first time control flow encounter this variable, it doesn't exist? – George Sovetov Mar 09 '16 at 17:25
  • @KurtStutsman, ok. He is wrong because his statement is not correct. There is no instance of static variable unles the function where it is defined was called at least once. Hence, `always one instance` is factually wrong. – SergeyA Mar 09 '16 at 17:25
  • A variable declared static in a header file that is included by multiple source files (translation units) will be created & Initialized X times because a static variable has internal linkage. Also, a static variable inside a method (member function) where the class is templated can be created and (and therefore initialized), more than once as well. IE: Class will not share the same static variable as Class. – Jts Mar 09 '16 at 18:26
  • A `static const` variable may be inserted directly into the executable because it is a constant, not really a variable. – Thomas Matthews Mar 09 '16 at 18:38
0

This looks like an attempt at premature optimization. Allegedly someone who created the code believed that by using static double variable they will save on creating the variable every time the function is entered.

However, since compilers are not morons, in practice it doesn't matter at all. Optimizing compilers will replace the variable with access to pre-allocated and initialized memory regardless, static or no static.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • 2
    There's really not enough context here to say it has anything to do with premature optimization. – Kurt Stutsman Mar 09 '16 at 17:25
  • @KurtStutsman, when you are presented with the code and being asked 'why it is done this way' you always guess. The quality of the guess depeneds on many factors. However, given the code this is the only reason I can think of why someone would use `static double` here. – SergeyA Mar 09 '16 at 17:28
  • "Allegedly" <-- you're the only one alleging this. – Barry Mar 09 '16 at 17:28
  • @Barry, at least two ansswers mention optimization of the variable creation as a reason for this. Your comment is factually wrong. – SergeyA Mar 09 '16 at 17:30
  • @SergeyA I would agree with you. – KyleEnglish Mar 09 '16 at 17:34
  • Remember the `const` modifier. A `static const` *variable* can be considered as a constant value and thus handled differently by the compiler. For example, the compiler may place constants directly into the code segment of the executable or into a "constants" segment which can be placed into read-only memory. Also, the `static const` allows the compiler to access the constant directly rather than copying it onto the stack. – Thomas Matthews Mar 09 '16 at 18:44
  • @ThomasMatthews, same thing with non-static const. It will still be put into initialized rodata section. – SergeyA Mar 09 '16 at 18:51
0

According to the OP's Code:

#includes...

static const int GLOBAL_CONST1 = 100;
static const double GLOBAL_CONST2 = 1.0;

SomeClass::SomeClass()
   :
      theDataMember1        (),
      theDataMember2        (),
      ...
{

   static const double SOME_VAR = 0.01; // Why not declare this globally?
   theDataMember1 = SomeIncludedClass(SOME_VAR);

}

One has to take into consideration a few things:

  • Data Storage Unit - Storage Class Specifier
  • Data Storage Duration - Minimum Life Of Data
  • Scope Visibility - Where The Data Unit Is Visible.

Here is an excerpt:

Global objects and objects in a namespace scope, static data members of a class, and local static objects in functions reside static storage duration. An object with static storage duration resides in the same memory address throughout the program's execution. Every such object is constructed only once during the lifetime of the program. By default, static data is initialized to binary zeros. Static objects with a nontrivial constructor or an explicit dynamic initializer undergo a second initialization phase called dynamic initialization.

The scope of an object declared static in a function is restricted to that function. Objects with static storage duration appear in the following examples:

int num=0; //global variables have static storage
extern int x; //also global, defined in a separate translation unit
int func()
{
  static int calls; //local static. initialized to 0 by default
  x=calls;
  return ++calls;
}

class C
{
private:
  static bool b;
};

namespace NS
{
  std::string str; //str has static storage
}

The extern Storage Class Specifier

The extern specifier can be applied only to the names of objects and to functions. The extern specifier cannot be used in the declaration of class members or function parameters. Identifiers declared extern have external linkage, meaning they are visible from all translation units of the same program.

A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage, meaning they are visible only from the translation unit in which they are declared.

Notice that the extern keyword is overloaded. It can also be used in explicit-instantiations of templates and in and linkage-specifications, but it is not a storage-class-specifier in such contexts.

The thread_local Storage Duration

The thread_local specifier indicates that the named object or reference has thread storage duration. thread_local shall be applied only to the names of objects or references of namespace scope and to the names of objects or references of block scope that also specify static as their storage class. The thread_local storage class is a new C++09 feature. It's discussed in detail here.

that can be found at this site: C++ Reference Guide | Static Storage Duration

The OP had stated and asked this:

I am working with a class whose constructor declares and initializes a static const variable in the implementation. This is not a data member of the class. I understand the use of const in this context, but what is gained by using static?

I understand that the static const global constants are shared by all instances of the class. Does that also happen with the variable inside the constructor?

Also, why would this not be defined at the Global scope, like the other two? That's where I would normally define my constants.

To answer his/her questions based on the excerpt above and from my own intuition:

  • their first question: "What is gained by using static?" static data storage units have automatic initialization. They are created only once and reside in that same memory address or allocation unit.
  • their second question: "Does that also happen with the variable inside the constructor?" Yes & No - Yes there is a single instance of this variable upon construction and initialization in the static storage memory unit, but no this is not visible to every instance of the class; it is only local to the Constructor of this class because of scope visibility.
  • their final question: "Also, why would this not be defined at the Global scope, like the other two?" This particular variable depending on intention of use might only be used in the initialization of another object. One of the benefits of this maybe to not having to use a stack variable, and is only visible to this class' constructor. So when this constructor is called ctor this static const variable is created and initialize only once per construction and once this class object's constructor goes out of scope this static const variable is no longer visible by any other function or member of this class, or any other translation unit that is outside the visibility of this scope.

There is no definitive answer, however I tried to provide as much insight as I can in regards to the OPs questions, and tried to answer them to the best of my abilities. Some of the things that can vary are the intentions of the programmer and the context in which these memory allocations units are, declared, defined, initialized and then used.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59