Why can I not initialize non-static member outside class declaration? - c++

class ClassObject {
public:
ClassObject();
virtual ~ClassObject();
private:
int x;
};
int ClassObject::x=10;
Why does it fail to compile?
I think that if static members can be initialized this way, then it should also be possible for non-static ones.

Static members are special. They have a memory allocated to them as soon as the class is defined. And no matter how many objects of that class we create all those objects refer to the same piece of memory.
This is not the case with non static members. Unless you create an object of that particular class, the non static members are not allocated any memory and hence trying to instantiate them in the above way leads to compiler error.

I'm guessing you mean declaring the value used to initialise x for any new ClassObject, i.e. you mean that as equivalent to
ClassObject() : x(10) { }
The problem with your syntax is that the compiler needs to generate code to do that initialisation in every ClassObject constructor; i.e. it can only work if the int ClassObject::x = 10; initialisation is available in the compilation unit that defines all constructors, and any compilation units that generate one implicitly. And the only way to guarantee that is if the value is set inside the class definition, not outside it as you have. (However this is now possible in C++11 - see the link in tacp's comment.)
If we did want to make your syntax work, then we'd need to store the declared value as a hidden static somewhere in a way that any constructors would pick it up and know to use it as the initial value for x. However this static may or may not exist, and the only point we can know that for a constructor in a different compilation unit is at link time. Hence we either generate extra, redundant code to initialise x from this hidden static if it exists (or redundant data) or we mandate link-time-code-generation to solve this, which puts a large burden on the compiler developer. It is possible, yes, but it's simpler all around if this isn't allowed.

Related

Why aren't C++ constructors capable of adding in new member variables?

It would make more intuitive sense to me if you could add in member variables in the constructor. This way, the class can adapt to changing input.
In C++ an object always has a fixed size. If constructors can add members at runtime, that guarantee goes out the window. In addition, in C++ all objects of the same type have the same size. Since a class can have multiple different constructors, the different constructors could specify different sizes.
This single, fixed size is the magic sauce that makes a number of C++'s high-performance tricks work, and in C++ convenience often gives way to speed. For example, an array of objects actually holds the objects. Not references to the objects, literally the objects. It can do this because everything in the array is the same size and the compiler can generate all of the indexing at compile time. CPUs love this because access is dead predictable and it can make full use of caches (assuming the access patterns you write allow it to do so). The more that's known and fixed at compile time, the more optimization opportunities the compiler has.
What you can do is add a member like a std::map or std::unordered_map that maps an identifier to its data. If all data is of the same type, this can be as easy as
std::map<std::string, int> members;
and access looks something like
members["hit points"] -= damage;
Note that while the map is inside the object, these mapped variables are not "inside" the object, They have to first be looked up in the map and then the data needs to be loaded from wherever it resides in in dynamic memory. This can slow down access considerably compared to a member that is known at compile time and reduced to an offset from the beginning of the object at a memory location that was probably already loaded into cache with the rest of the object.
Let's say we add that to the standard. Let's say we decide to introduce new keyword append to create new class member from within constructor. Then, one could have a following class:
struct A
{
A(int n) {
append int x = n;
}
A(std::string s) {
append std::string str = s;
}
};
Now, what is the sizeof(A)? Is it sizeof(int) or sizeof(std::string)? Remember that sizeof is a compile time operation. Compiler must be able to know that, it cannot be deferred to runtime.
And one more example:
void foo(A a)
{
std::cout << a.x; //should this compile?
std::cout << a.str; //or should this compile?
}
How would compiler know if a has member x or member str accessible to foo? Compilation in C++ is done in translation units, with each translation unit being compiled completely separately from the others. If foo() is defined in foo.cpp and it is called from main.cpp, compiler would have no idea which operation is valid. Moreover, both could be valid, just for different A objects.
C++ has many ways to add some flexibility to amount of members in classes, notably inheritance (to add new members) and templates (to create members of different type in the same class template). There is no need to try to introduce mechanisms from interpreted languages like Python.

force a global variable to be initialized before a certain static field

I want the global variable's initialization (#A) to be called before initialization of static field (#B).
Currently, some static fields are initialized before global variable.
GridUtil.h
class GridUtil{
static Vec4* bPtr_; //will be filled
static void initGridCalculationCache();
static class _init //helper class
{
public:
_init() {
static_iniAll();
}
} _initializer;
}
GridUtil.cpp
#include "GridUtil.h"
GridUtil::_init GridUtil::_initializer;// (Edit: This line is just added, thank Dietmar Kühl.)
Vec4 b[24]; //#A executed 3rd : No, this should be the first.
Vec4* GridUtil::bPtr_=b; //#B executed 1st
void GridUtil::initGridCalculationCache() {
//.... fill GridUtil::bPtr_ using complex computation //#C executed 2nd
}
Result
From debugging, the execution order of above code is:-
B->C->A
But I want :-
A->B->C
I noticed that if "Vec4" is replaced by "int", the execution order will be:-
A->B->C
The objective is to set value of elements in the array (bPtr_) using a static function (initGridCalculationCache) that would be called automatically (helped by class _init).
If it is not possible, what is a correct way to do it?
The four obvious solutions in order of preference are:
Do not have global or static member variables to start with! These tend to create a large amount of problems, doubly so in systems utilizing concurrency.
Use constexpr objects as these get initialized during compilation time. There are, obviously, some constraints on what can be done but the compiler would verify that objects are initialized in the proper order.
Within a translation unit objects with static live time are initialized from top to bottom. That is, using the proper order if variable definition may achieve the desired order. There is, however, no portable approach ordering varriable initialization across translation units.
When there are dependencies on initialization between objects from different translation units the correct order can be guaranteed using function local static objects to which a reference is returned: these will be constructed upon first access.
The order is rather simple, POD are initialized by copying them from the .DATA section of your binary to RAM. Classes are initialized at runtime by their ctor. Therefore POD will allways be initialized befor any class with a ctor as long as they are in the same static area. If you use DLL/SO everything gets funny.
The order of initialization is undefined. There are no guarantees for anything. If you explicitly need an special order, initialize your static vars in an init function.

memory layout of two C++ classes sharing the same members

Suppose I have a class X such that all its non-static members are PODs, and a class Y that has the same members in the same order as X, and is also POD itself. Is it legal to reinterpret_cast an instance of Y to X? If it's not, will it work in practice across platforms?
To give you a bit of background, my class X has itself as static members for convenience (i.e. class X { ... public: static const X& a; static const X& b; }, and I want to remove static initializers without changing the API. My plan was to create global static objects of Y type and reinterpret_cast them to X -- since all members are POD, I don't need constructor to be run.
Assuming the layout of the members are exactly the same and you are not introducing any inheritance you can "safely" reinterpret_cast. I put "safely" in quotes for a reason, doing this seems simply a bad idea, you say you want to
...remove static initializers without changing the API. My plan was to create global static objects...
Why would you do this? Keeping a set of static variables in a class has only one drawback, you have to type the name of the class whenever you use it. Also adding the static keyword to a global variable doesn't behave the same as in a class declaration. static when appended to a global variable means that the compiler will only use it in the scope of the translation unit. This means that you could potentially have multiple globals with the same name in separate files. Again this is only adding to the complexity, though you did not specify why you want to do this exactly, i can safely say that what you are trying to accomplish should be and could be solved in a much more scope-oriented fashion.

Persistent class variables

I have a question regarding static variables, or some other way to do so.
I have a master class, PatternMatcher. I have several derived units from that, depending on what matcher is used. Now each subclass needs to store a vector of floats, but within each class it is constant. The data for that vector is read during initialization, and can be up to 1GB in size (smallest I have is 1MB, biggest is 1GB).
Currently when I have for example two instances of Matcher_A, it would allocate twice the memory. I do not know in advance which matchers are to be used (per run it will be three matchers, and you can use the same matcher several times). I would prefer to not check during run time whether the wanted matcher is already initialized somewhere, since this would require additional code for every change I do.
Currently I allocate the 3 matchers with
PatternMatcher* a = new PMMatcherA();
PatternMatcher* b = new PMMatcherB();
PatternMatcher* c = new PMMatcherC();
, but since they are user selected, it could happen that A and C are the same for example. When I run a check via typeid(a).name();, it would give me PatternMatcher as result, never matter what class I used to initiate with. PatternMatcher basically is purely a virtual class.
I always thought that static means that a variable is constant over different allocations, but when I define my vector as static, I would get a linker resolve error. In an earlier iteration, I had these vectors global, but would prefer them to be localized to their classes.
What are the keywords I need to use to have the vector from on initialization be available for the next initialization already? A simple check if the vector size is greater than 0 would already be enough, but every object uses its own vector.
static keyword is a way to go - that would store exactly one copy of a member for the whole class. What you were missing is an actual declaration of such static in a compilation module so that the linker can use it. For instance:
header file foo.h:
struct Foo {
static int s_int;
}
source file foo.cpp:
#include "foo.h"
int Foo::s_int; // optionally =0 for initialization
The second part is vital as this will allocate a memory space for the object to be used as a static member.
Keep in mind, though, that:
static members will all be initialized before the main(), which means your 1GB of data will be read regardless of whether anyone ever uses that particular class
You can work around the abovementioned issue, but then you will have to be checking if the data load and initialization has happened during run-time
There's another option for you, however. If you store your floats "as-is" (i.e. 32 bits per each, in binary format) you can just simply "map" the files into memory spaces and access them as if they were already loaded - the OS will take care of loading appropriate 4K pages into RAM when needed.
Read more about mmap at http://en.wikipedia.org/wiki/Mmap
Yes, static is what you need. You can use it like this:
class MyClass
{
private:
static std::vector< float > data_;
};
std::vector< float > MyClass::data_;
Please note that in the class itself you only declare static variables. But you also need to define them outside of the class exactly once. That's why we have the line std::vector< float > MyClass::data_;, if you omit that, you will have linker errors.
After this, every object of MyClass class will share the same data_ vector.
You can operate it either from any object of the class:
MyClass a;
a.data_.push_back(0);
or through the class name:
MyClass::data_.push_back(0);
when I define my vector as static, I would get a linker resolve
error.
This is because you declare the static variable (in your header file) but you never explicitly initialize it in one of your implementation file (.cpp).
For example:
//AClass.h
class AClass
{
private:
static std::vector<int> static_vector;
};
and in the .cpp implementation file:
std::vector<int> AClass::static_vector;

Find the list of member variables of a class and their types?

I haven't ever heard it's possible, but asking with the hope that it might.
For a class with many more member variables than this:
class A
{
public:
SomeOtherClass* s;
int i;
int j;
A() {}
A(const A& soc): s(soc.s->Clone()), i(soc.i), j(soc.j) {}
};
I always have to remember that if I add another variable int k to the class, I'll also have to add it in the initialization list k(soc.k) and sometimes in the destructor too.
I've had to add/remove member variables so many times and it's really annoying to forget about the copying in the initialization list and finding the omission much much later while debugging.
Therefore, I wanted to know if there's a syntax/logic through which I can find out the list of member variables of a class and their types, so that I can maybe iterate through them and decide which of them need to be copied in the copy ctor and which of them need to be deep copied?
I don't see why the creators of C++ couldn't have included such a facility, since except for virtual members, the memory locations of variables would be contiguous and their types are known too. Even if they were extern or virtual, the type and size would be known at runtime. So shouldn't it be possible?
There is no reflection in C++, so you'll need an external library to do this. The creators of C++ didn't implement this feature because it implies a performance penalty, and performance is one of C++'s main goals.
I always have to remember that if I add another variable int k to the class, I'll also have to add it in the initialization list k(soc.k) and sometimes in the destructor too.
Yep, you do.
I've had to add/remove member variables so many times and it's really annoying to forget about the copying in the initialization list and finding the omission much much later while debugging.
Yes, it is.
Therefore, I wanted to know if there's a syntax/logic through which I can find out the list of member variables of a class and their types, so that I can maybe iterate through them and decide which of them need to be copied in the copy ctor and which of them need to be deep copied?
No, there isn't.
I don't see why the creators of C++ couldn't have included such a facility, since except for virtual members, the memory locations of variables would be contiguous and their types are known too. Even if they were extern or virtual, the type and size would be known at runtime. So shouldn't it be possible?
Yes, ideally.
C++ isn't really "that sort of a language", but it is a bit of a pain.
please consult
http://yosefk.com/c++fqa/defective.html#defect-6
for a point of view on the topic.
and as an answer, basically you can't do it.
Yes well it do not answer your question but to solve your problem what I did in my code is to use a struct to hold the members that can be copied automatically so that I don't have to worry about them.
class A
{
public:
SomeOtherClass* s;
class Members
{
int i;
int j;
};
Members m;
A() {}
A(const A& soc): s(soc.s->Clone()), m(soc.m) {}
void f() {
m.j;//use j
}
};
But generally I prefer to use deep_copy pointers so that I don't even need that trick (pointer are also copied automatically, when I can).
I posted about it some time ago : https://stackoverflow.com/questions/469696/what-is-your-most-useful-c-c-utility/1609496#1609496.
I'm not sure this will solve your problem with destructor (maybe the deep_copy pointer will).
If you're interested, I also suggest to check the posts that were talking about memberspace here on stackoverflow, which was basically using the same kind of trick for other means if I remember correctly.
As noted, there is no reflection in C++. One simple thing you might do would be to check the size of the class. This could at least get you to look at the proper location by generating an error message if you forget to update the size after adding a member.
Example:
template<size_t Real, size_t Expected> struct check_size;
template<size_t Size> struct check_size<Size, Size> {};
// ...
A(const A& soc): s(soc.s->Clone()), i(soc.i), j(soc.j) {check_size<sizeof(A), 24> size_checker;}
I always have to remember that if I add another variable int k to the
class, I'll also have to add it in the initialization list k(soc.k)
and sometimes in the destructor too.
No you do not have to. Just leave everything public and do not provide constructors destructors. Aggregate initialization will handle that. If you need something private this means you have encapsulation and list of constructors should be fixed no matter what are the fields.
If you are warring about resources leak just use RAII pattern, in case of pointers std::unique_ptr and std::shared_ptr
Now about title:
Find the list of member variables of a class and their types?
If you can use Aggregate initialization there is super cool template only (no macros) library boost pfr which can do that.
Here is a talk where library author explains how it works.