How to define a Struct with default values? - c++

Rather surprised to find this question not asked before. Actually, it has been asked before but the questions are VERY DIFFERENT to mine. They are too complicated and absurd while I'll keep it simple and to the point. That is why this question warrants to be posted.
Now, when I do this,
struct A {
int a = -1;
};
I get the following error:
ANSI C++ forbids in-class initialization of non-const static member a
Now, along with the workaround can someone please tell me THE BEST way of initializing a struct member variable with a default value?

First, let's look at the error:
ANSI C++ forbids in-class initialization of non-const static member a
Initialization of a true instance member, which resides within the memory of an instance of your struct is the responsibility of this struct's constructor.
A static member, though defined inside the definition of a particular class/struct type, does not actually reside as a member of any instances of this particular type. Hence, it's not subject to explaining which value to assign it in a constructor body. It makes sense, we don't need any instances of this type for the static member to be well-initialized.
Normally, people write member initialization in the constructor like this:
struct SomeType
{
int i;
SomeType()
{
i = 1;
}
}
But this is actually not initialization, but assignment. By the time you enter the body of the constructor, what you've done is default-initialize members. In the case of a fundamental type like an int, "default-initialization" basically boils down to "eh, just use whatever value was in those bytes I gave you."
What happens next is that you ask i to now adopt the value 1 via the assignment operator. For a trivial class like this, the difference is imperceptible. But when you have const members (which obviously cannot be tramped over with a new value by the time they are built), and more complex members which cannot be default-initialized (because they don't make available a visible constructor with zero parameters), you'll soon discover you cannot get the code to compile.
The correct way is:
struct SomeType
{
int i;
SomeType() : i(1)
{
}
}
This way you get members to be initialized rather than assigned to. You can initialize more than one by comma-separating them. One word of caution, they're initialized in the order of declaration inside your struct, not how you order them in this expression.
Sometimes you may see members initialized with braces (something like i{1} rather i(c)). The differences can be subtle, most of the time it's the same, and current revisions of the Standard are trying to smooth out some wrinkles. But that is all outside the scope of this question.
Update:
Bear in mind that what you're attempting to write is now valid C++ code, and has been since ratification of C++11. The feature is called "Non-static data member initializers", and I suspect you're using some version of Visual Studio, which still lists support as "Partial" for this particular feature. Think of it as a short-hand form of the member initialization syntax I described before, automatically inserted in any constructor you declare for this particular type.

You could make a default constructor
struct A {
A() : a{-1} {}
int a;
};

Related

How can I detect whether a class has an implicit constructor AND primitive members in c++?

I want to detect during compile time (static assertion) whether a class meets both the following conditions:
Has an implicit default constructor (i.e., no user-defined default constructor).
Has at least one data member which is a pod (i.e., a member whose default initialization is to assume whatever random bytes was in its memory address).
[I hope I used the term pod correctly here]
The idea is to avoid working with objects with uninitialized members. I know there are different methods to do this during coding, but I also want a mechanism to detect this during compilation.
I tried using different std/boost functions, such as is_trivially_constructible, is_pod, but none of these provide the exact terms I need.
For example, let's say I have the following classes:
struct A
{
int a;
}
struct B
{
int* b;
}
struct C
{
bool c;
std::string c_str_;
}
struct D
{
D();
float d;
}
struct E
{
std::string e;
}
Assuming the function I need is called "has_primitive_and_implicit_ctor", I would like the output for each call to be as in the comments:
has_primitive_and_implicit_ctor<A>(); //true - A has at least one pod type member (int)
has_primitive_and_implicit_ctor<B>(); //true - A has at least one pod type member (pointer)
has_primitive_and_implicit_ctor<C>(); //true - A has at least one pod type member (bool), even though there is one non-pod member
has_primitive_and_implicit_ctor<D>(); //false - has a pod member(float), but a user defined ctor
has_primitive_and_implicit_ctor<E>(); //false - doesn't have a default ctor but has no pod members
Firstly, it seems to me like a broken design to expect from the user of a class to care about its member initialisation. You should make sure in the class itself that all its members are initialised, not somewhere else where it is used.
What you are looking for does not exist, and if it would, it would not even help you. The existence of an explicit constructor does not guarantee that a data member is initialised. On the other hand, with C++11 it is even possible to initialise data members without explicitly writing a constructor (using the brace syntax in the class declaration). Also you just seem to care about uninitialised POD members, but what about uninitialised non-POD members?
That said, compiler can generate warnings about uninitialised values, but often you have to enable this warning (e.g. -Wuninitialized option for gcc). Most compilers allow to force treating warnings as an error. In combination this can give you the desired effect even without specifically writing code to test for it, and it would also work for any uninitialised values, not only those in classes. Maybe this is the solution you are looking for.

How do I avoid needing to initialize a member object in the initialization list?

I am writing a C++ application that makes use of plenty of child objects nested within one 'root' object.
Each of these needs to be initialized in a specific order, with various operations being done between each initialization, and sometimes needing to have previously-initialized ones as arguments to each other.
However, my compiler is forcing me to initialize these in the constructor's initializer list, insisting that initializing within the constructor is not enough. For example, I could not do the following:
SomeThing::SomeThing() {
int argGottenByLibraryCall;
someLibraryCallToGetArg(&argGottenByLibraryCall);
m_ChildObject = ChildClass(argGottenByLibraryCall);
}
I have taken to implementing a post-creation initializer function instead:
SomeThing::SomeThing() : m_ChildObject() {
int argGottenByLibraryCall;
someLibraryCallToGetArg(&argGottenByLibraryCall);
m_ChildObject.Initialize(argGottenByLibraryCall);
}
This, however, seems like a poor practice for me to follow. Is there a better way of making my compiler (VC++ 2017) accept initialization within the constructor body?
This, however, seems like a poor practice for me to follow.
The poor practice is not using initialization lists. They allow you to mark your data members as const and also ensure that they are initialized.
The correct way to solve your problem is to restructure your code so that m_ChildObject has a proper constructor that can be used in the member initialization list.
If that is not possible, wrap your initialization logic in a function and use that in the member initialization list:
ChildObjectType makeChildObject() {
int argGottenByLibraryCall;
someLibraryCallToGetArg(&argGottenByLibraryCall);
ChildObjectType result;
result.Initialize(argGottenByLibraryCall);
return result;
}
// ...
SomeThing::SomeThing() : m_ChildObject(makeChildObject()) { }

Get address of a non-POD object from within a data member, which is a single-use nested class

I'll start with some code:
class myNonPODClass
{
public:
virtual ~myNonPODClass() {}
class
{
public:
myNonPODClass* GetContainer()
{
return (myNonPODClass*)((int8_t*)(this) - offsetof(myNonPODClass, member));
}
} member;
};
Obviously, this is a contrived example. The code compiles fine, but I'm worried about the "Offset of on non-POD type 'myNonPODClass'". Is there a better way to do essentially the same thing WITHOUT having to pass the myNonPODClass pointer into the nested anonymous classes constructor (or similar)? "member" must be ready to go without any initialization. Is it possible? Thanks!
In case you're wondering what on Earth I could want this for, my PROPERTY macro and a commented out example on pastebin (yes, it's awesome ^^ ): http://pastebin.com/xnknf39m
This code does not work, per the C++ specification, for several reasons:
offsetof requires a POD type (in C++11, it requires a standard-layout type). Your type is not, and therefore calling it results in undefined behavior.
The conversion to int8_t* and then to another type is undefined behavior per the C++ specification. You would need to use a char*, which has certain relaxed casting rules.

When should we not use initialization list in the constructor?

Can someone please quote an example code when we should not use initialisation list in the constructor and how that can be overcome with assignment?
I am looking for an example for the below statement
This might happen when your class has two constructors that need to initialize the this object's data members in different orders. Or it might happen when two data members are self-referential. Or when a data-member needs a reference to the this object, and you want to avoid a compiler warning about using the this keyword prior to the { that begins the constructor's body (when your particular compiler happens to issue that particular warning). Or when you need to do an if/throw test on a variable (parameter, global, etc.) prior to using that variable to initialize one of your this members.
I believe the main concept that the author of your statement was referring to is the fact that calls made to variables in the initialisation list occur not in the order you see them in the initialisation list, but in the order the variables are listed in the class definition.
That means
if you have two different constructors which use initialisation lists, they must initialise them in the same sequence
your control over sequencing (which may be important if you have mutually-dependent members) is limited
I'd recommend taking a look at Scott Meyer's Effective C++ which covers this (amongst many, many other useful and informative topics).
Here are some examples:
This might happen when your class has two constructors that need to
initialize the this object's data members in different orders.
class Example1 {
public:
Example1(std::string decoded, std::string encoded)
: decoded_(decoded),
encoded_(encoded) {}
explicit Example1(std::string encoded)
: decoded_(), // Can't use "decoded_(Decode())" since "encoded_" isn't initialised
encoded_(encoded) {
decoded_ = Decode(); // Assign here instead of initialising
}
private:
std::string Decode(); // decodes class member "encoded_"
std::string decoded_, encoded_;
};
In this example, decoded_ will always be initialised before encoded_ since that's the order in which they are declared in the class, even if we swap their order in the initialisation list.
Or when a data-member needs a reference to the this object, and you
want to avoid a compiler warning about using the this keyword prior to
the { that begins the constructor's body (when your particular
compiler happens to issue that particular warning).
class Example2 {
public:
Example2() : functor_() {
functor_ = std::bind(&Example2::Do, this);
}
private:
void Do();
std::function<void()> functor_;
};
Here, functor_ needs to use this when it is initialised/assigned. If we were to intialise functor_ in the initialisation list, the this pointer would be referring to an object which at that point wasn't fully initialised. That could be safe depending on the particular circumstances, but the foolproof option is to defer setting functor_ until inside the constructor body, by which point this does refer to a fully-initialised object.
Or when you need to do an if/throw test on a variable (parameter,
global, etc.) prior to using that variable to initialize one of your
this members.
class Example3 {
public:
Example3(int force, int acceleration)
: force_(force),
acceleration_(acceleration),
mass_(0) {
if (acceleration_ == 0)
throw std::exception("Can't divide by 0");
mass_ = force_ / acceleration_;
}
private:
int force_, acceleration_, mass_;
};
Hopefully this is self-explanatory.
I'm not sure what is meant by
when two data members are self-referential
so I can't give an example for that I'm afraid.

C++ Constructor initialization list strangeness

I have always been a good boy when writing my classes, prefixing all member variables with m_:
class Test {
int m_int1;
int m_int2;
public:
Test(int int1, int int2) : m_int1(int1), m_int2(int2) {}
};
int main() {
Test t(10, 20); // Just an example
}
However, recently I forgot to do that and ended up writing:
class Test {
int int1;
int int2;
public:
// Very questionable, but of course I meant to assign ::int1 to this->int1!
Test(int int1, int int2) : int1(int1), int2(int2) {}
};
Believe it or not, the code compiled with no errors/warnings and the assignments took place correctly! It was only when doing the final check before checking in my code when I realised what I had done.
My question is: why did my code compile? Is something like that allowed in the C++ standard, or is it simply a case of the compiler being clever? In case you were wondering, I was using Visual Studio 2008
Yes, it's valid. The names in the member initializer list are looked up in the context of the constructor's class so int1 finds the name of member variable.
The initializer expression is looked up in the context of the constructor itself so int1 finds the parameter which masks the member variables.
What you have done is standard C++. Only member variables or base classes may be initliazed in the initialization list, so the variable outside the paranthesis is unambiguous. Within the parenthesis, the typical scoping rules apply, and the members are overshadowed by the parameter names.
This is perfectly normal behavior. As AAT rightly pointed out, there is no ambiguity. The variables initialised by the list have to be class members. This is standard and works across all compliant compilers.
The only thing to remember while using a list like this is that a person who doesn't understand this kind of code may have to maintain it. There is nothing wrong with writing initialisation code like this as long as you know what you are doing.
I imagine this works because you were using int1 in the initialiser list, and the only things you can initialise are member variables => it was in fact unambiguous which variable was being initialised.
Whether all C++ compilers would be this forgiving is another matter!
What you have done is normal. This kind of implementation avoids you from even using the 'this' pointer (in this case).