"Only static constant integral variables may be initialized within a class " - c++

can someone explain to me why cant i initialize a static variable inside the class ? what happens in compilation time exactly ?
for example :
class Object {
static int numberOfObjects = 0; // This gives the error
Object(){
nummberOfObjects++;
}
};
Thanks !

It's just a rule from the standard that was implemented by the compiler. The fact that it was a rule doesn't mean the opposite isn't possible, as the change in the newer C++11 standard and according compilers show.

In versions of C++ prior to C++11, the language standard simply doesn't allow you to perform a static variable definition inside the class declaration. In other words, You can't initialize it because it isn't constant. Since it can change during execution, the compiler needs some memory allocated somewhere to actually keep the value in. Since this is a class declaration, it doesn't actually allocate the memory for you. This issue doesn't exist for const values because they don't need memory assigned -- they are effectively "hard coded" just like if you replaced them with literals (or an old 'C' style #define).
You need a line of code outside of the class declaration that basically says:
int Object::numberOfObjects = 0;
This line isn't just initializing the static class variable, it's actually allocating a static int that will be used to store the value. The line of code up in the class declaration doesn't do this -- it merely tells the compiler that such a value exists somewhere.
Note that starting with C++11 this behavior is different. The language is now smart enough to figure out that you DO want to that memory defined, so you no longer need to do so manually.

Related

Are C++ aggregate initializers effective at run time or compile time?

TL;DR : I need global objects to be initialized at compile time, and I cannot use constexpr constructors. Can I use aggregate initializers for this task?
I know that C/C++ aggregate initializers can be used to initialize an object's public members like this :
MyObj obj = { "object1", 3, 7.2F };
I discovered their existence not long ago, and I thought about a previous issue I had.
I have a global object with a class type which I'm currently initializing using a constructor :
MyObj obj = MyObj("object1", 3, 7.2F);
This constructor only sets a few members with the given arguments. The problem is that I'd like the object's members to already be initialized inside the application's executable (like a compile-time constructor), which is not the case. Yes, I have inspected the resulting binary file, and the object's space is zeroed.
I cannot use constexpr on the constructor, because I'm working without modern C++ and have no way to upgrade.
This is why I'd like to know if I can use aggregate initializers to solve my issue.
EDIT 1 : I forgot to mention that I am developing for Windows, and that the objects I want to initialize have the __declspec(dllexport) and extern "C" specifiers.
As n. 1.8e9-where's-my-share m. said, the terms "compile-time" and "run-time" are meaningless as far as the language is concerned. They are more likely to concern the toolset you're working with.
Best answer I can give here is "uncertain". The behavior of aggregate initializers is not part of the C++ standard, which means it is implementation-defined.
To answer my problem, the best bets I have are either switching to modern C++ and use constexpr constructors, or writing my data in ASM files.

is static const in C++ same as const in C? [duplicate]

This question already has answers here:
Static variables in C++
(3 answers)
Closed 8 years ago.
In C header file:
const int AvarInC = 1;
Now in C++ file:
class Cpp
{
public:
static const int PublicAvar = 1;
private:
static const int Avar = 1;
};
while i have:
const int AvarInC = 1; in my C headers
OR
static const int AvarInC = 1; in my C headers.
Will it be the same thing? Is the first one without keyword static, implicitly static?
It is similar. Of course, you can use the C way in C++ as well.
But the specific C++ way (a class member) also differs in visibility and scope. Only code that is part of class Cpp (or a friend) can access Avar. The PublicAvar is somewhere in between; anyone can access it, but they need to refer to it as Cpp.PublicAvar.
The keyword static has two distinct meanings in C++. Sometimes it means the storage class (as in your example) - that is, "this is not a per-instance member". In this respect, a variable which is not a member of a class at all is obviously static without having to declare that.
Other times, static may refer to link-time visibility. A static symbol is only valid inside its own compilation unit. That's the original C meaning. It does not come into your example especially because we are assuming that your code goes in a header file, and is therefore present in multiple compilation units. Marking a non-member variable as static would result in a number of copies of the variable in the program (one per compilation unit) which would not hurt for a const variable, but generally it could lead to very confusing program behavior.
If I understand you correctly, no they aren't quite the same. Since you are putting the C one in a header file, I'm assuming it will be a global constant, therefore there will really only be one copy of it anyways. It won't need to be recreated each time (since that what static will do.
However, the one in the C++ file is inside a class and static, so every time that class is instantiated into an object all instances will share the same copy of the PublicAvar variable and it won't get recreated with each object.
Though, I have a feeling you knew what static does. So technically no, they don't do the same thing and aren't the same thing...but they do act similarly.
I'm not an expert, so I could be wrong but I believe this is right. Hope it helps.
No, they are not same. They are both variables are initialized at compile time. But static variable can be accessed without creating any object of a class, but non static variable only exists within an object. i.e, the static variable takes common space in the memory for any number of objects created for it, but not in case of the other one.
"The same" is quite ambiguous. Both will be treated as compile-time constant. You can (should) not change them at runtime and the compiler can decide to use this information to optimize your code.

is static const string member variable always initialized before used?

In C++, if I want to define some non-local const string which can be used in different classes, functions, files, the approaches that I know are:
use define directives, e.g.
#define STR_VALUE "some_string_value"
const class member variable, e.g.
class Demo {
public:
static const std::string ConstStrVal;
};
// then in cpp
std::string Demo::ConstStrVal = "some_string_value";
const class member function, e.g.
class Demo{
public:
static const std::string GetValue(){return "some_string_value";}
};
Now what I am not clear is, if we use the 2nd approach, is the variable ConstStrVal always initialized to "some_string_value" before it is actually used by any code in any case? Im concerned about this because of the "static initialization order fiasco". If this issue is valid, why is everybody using the 2nd approach?
Which is the best approach, 2 or 3? I know that #define directives have no respect of scope, most people don't recommend it.
Thanks!
if we use the 2nd approach, is the variable ConstStrVal always initialized to "some_string_value" before it is actually used by any code in any case?
No
It depends on the value it's initialized to, and the order of initialization. ConstStrVal has a global constructor.
Consider adding another global object with a constructor:
static const std::string ConstStrVal2(ConstStrVal);
The order is not defined by the language, and ConstStrVal2's constructor may be called before ConstStrVal has been constructed.
The initialization order can vary for a number of reasons, but it's often specified by your toolchain. Altering the order of linked object files could (for example) change the order of your image's initialization and then the error would surface.
why is everybody using the 2nd approach?
many people use other approaches for very good reasons…
Which is the best approach, 2 or 3?
Number 3. You can also avoid multiple constructions like so:
class Demo {
public:
static const std::string& GetValue() {
// this is constructed exactly once, when the function is first called
static const std::string s("some_string_value");
return s;
}
};
caution: this is approach is still capable of the initialization problem seen in ConstStrVal2(ConstStrVal). however, you have more control over initialization order and it's an easier problem to solve portably when compared to objects with global constructors.
In general, I (and many others) prefer to use functions to return values rather than variables, because functions give greater flexibility for future enhancement. Remember that most of the time spent on a successful software project is maintaining and enhancing the code, not writing it in the first place. It's hard to predict if your constant today might not be a compile time constant tomorrow. Maybe it will be read from a configuration file some day.
So I recommend approach 3 because it does what you want today and leaves more flexibility for the future.
Avoid using the preprocessor with C++. Also, why would you have a string in a class, but need it in other classes? I would re-evaluate your class design to allow better encapsulation. If you absolutely need this global string then I would consider adding a globals.h/cpp module and then declare/define string there as:
const char* const kMyErrorMsg = "This is my error message!";
Don't use preprocessor directives in C++, unless you're trying to achieve a holy purpose that can't possibly be achieved any other way.
From the standard (3.6.2):
Objects with static storage duration (3.7.1) shall be zero-initialized
(8.5) before any other initialization takes place. A reference with
static storage duration and an object of POD type with static storage
duration can be initialized with a constant expression (5.19); this is
called constant initialization. Together, zero-initialization and
constant initialization are called static initialization; all other
initialization is dynamic initialization. Static initialization shall
be performed before any dynamic initialization takes place. Dynamic
initialization of an object is either ordered or unordered.
Definitions of explicitly specialized class template static data
members have ordered initialization. Other class template static data
members (i.e., implicitly or explicitly instantiated specializations)
have unordered initialization. Other objects defined in namespace
scope have ordered initialization. Objects defined within a single
translation unit and with ordered initialization shall be initialized
in the order of their definitions in the translation unit. The order
of initialization is unspecified for objects with unordered
initialization and for objects defined in different translation units.
So, the fate of 2 depends on whether your variable is static initialised or dynamic initialised. For instance, in your concrete example, if you use const char * Demo::ConstStrVal = "some_string_value"; (better yet const char Demo::ConstStrVal[] if the value will stay constant in the program) you can be sure that it will be initialised no matter what. With a std::string, you can't be sure since it's not a POD type (I'm not dead sure on this one, but fairly sure).
3rd method allows you to be sure and the method in Justin's answer makes sure that there are no unnecessary constructions. Though keep in mind that the static method has a hidden overhead of checking whether or not the variable is already initialised on every call. If you're returning a simple constant, just returning your value is definitely faster since the function will probably be inlined.
All of that said, try to write your programs so as not to rely on static initialisation. Static variables are best regarded as a convenience, they aren't convenient any more when you have to juggle their initialisation orders.

when to declare an member of class

According to Bjarne Stroustrup:
if (and only if) you use an initialized member in away that requires it to be stored as an oject in memory ,the member must be(uniquely) defined somewhere. The initializer may not be repeated.
(The C++ Programming Language, 3rd Edition, Section 10.4.6.1)
He gives this example:
class curious{
public:
static const int c1=7;
//..
};
const int curious::c1; //necessary
Then why it is necessary to define a static member, because we may not be initializing it at all?
Also, const and reference members are not declared anywhere, even though it is necessary to initialize them (no default constructor).
If you don't use c1 in a way that requires it to be stored in memory (such as taking the address, etc) the compiler can replace all uses of c1 with the value 7. However, if you use it in such a way that it needs to be stored somewhere, then you have to provide a definition so that it exists in some compilation unit.
Member variables are not declared anywhere because they exist inside the object when it is created; each member variable lives inside the object that is created. static variables exist apart from any object instance (that is, the static variable exists regardless of whether the class is instantiated or not) so they need somewhere to live (sometimes) which is independent of a specific instance.

Difference between static in C and static in C++??

What is the difference between the static keyword in C and C++?
The static keyword serves the same purposes in C and C++.
When used at file level (outside of a function), it sets the visibility of the item it's applied to. Static items are not visible outside of their compilation unit (e.g., to the linker). Their duration is the same as the duration of the program.
These file-level items (functions and data) should be static unless there's a specific need to access them from outside (and there's almost never a need to give direct access to data since that breaks the central tenet of encapsulation).
If (as your comment to the question indicates) this is the only use of static you're concerned with then, no, there is no difference between C and C++.
When used within a function, it sets the duration of the item. Again, the duration is the same as the program and the item continues to exist between invocations of that function.
It does not affect the visibility of that item since it's visible only within the function. An example is a random number generator that needs to keep its seed value between invocations but doesn't want that value visible to other functions.
C++ has one more use, static within a class. When used there, it becomes a single class variable that's common across all objects of that class. One classic example is to store the number of objects that have been instantiated for a given class.
As others have pointed out, the use of file-level static has been deprecated in favour of unnamed namespaces. However, I believe it'll be a cold day in a certain warm place before it's actually removed from the language - there's just too much code using it at the moment. And ISO C have only just gotten around to removing gets() despite the amount of time we've all known it was a dangerous function.
And even though it's deprecated, that doesn't change its semantics now.
The use of static at the file scope to restrict access to the current translation unit is deprecated in C++, but still acceptable in C.
Instead, use an unnamed namespace
namespace
{
int file_scope_x;
}
Variables declared this way are only available within the file, just as if they were declared static.
The main reason for the deprecation is to remove one of the several overloaded meanings of the static keyword.
Originally, it meant that the variable, such as in a function, would be given storage for the lifetime of the program in an area for such variables, and not stored on the stack as is usual for function local variables.
Then the keyword was overloaded to apply to file scope linkage. It's not desirable to make up new keywords as needed, because they might break existing code. So this one was used again with a different meaning without causing conflicts, because a variable declared as static can't be both inside a function and at the top level, and functions didn't have the modifier before. (The storage connotation is totally lost when referring to functions, as they are not stored anywhere.)
When classes came along in C++ (and in Java and C#) the keyword was used yet again, but the meaning is at least closer to the original intention. Variables declared this way are stored in a global area, as opposed to on the stack as for function variables, or on the heap as for object members. Because variables cannot be both at the top level and inside a class definition, extra meaning can be unambiguously attached to class variables. They can only be referenced via the class name or from within an object of that class.
It has the same meaning in both languages.
But C++ adds classes. In the context of a class (and thus a struct) it has the extra meaning of making the method/variable class members rather members of the object.
class Plop
{
static int x; // This is a member of the class not an instance.
public:
static int getX() // method is a member of the class.
{
return x;
}
};
int Plop::x = 5;
Note that the use of static to mean "file scope" (aka namespace scope) is only deoprecated by the C++ Standard for objects, not for functions. In other words,:
// foo.cpp
static int x = 0; // deprecated
static int f() { return 1; } // not deprecated
To quote Annex D of the Standard:
The use of the static keyword is
deprecated when declaring objects in
namespace scope.
You can not declare a static variable inside structure in C... But allowed in Cpp with the help of scope resolution operator.
Also in Cpp static function can access only static variables but in C static function can have static and non static variables...😊