Related
I have a structure that has 3 different types of values in it (char, float, int).......I need to set everything to 0 at the beginning of the program. How do I do that?
There are two usual ways:
A a = A();
or
A a = {};
The first has the advantage that if you later provide
constructor, it still works (as long as you provide a default
constructor).
With regards to the suggestion to use memset: memset is only
guaranteed to work for integral types. I can't imagine it not
working for a float, but formally, it's not guaranteed. And
of course, if you later modify the struct, it might stop
working. It is a solution to avoid.
struct A
{
int a;
char b;
float c;
};
struct A is an aggregate, built-in types initialized to 0. You can initialize to A in two ways:
//Class method pass to function
int main()
{
A a = {}; // initialize single A to 0
A b = A(); // same effort
A c[10] = {}; // initialize array to 0
return 0;
}
You could make use of a constructor to initialise all of your elements. So you will be able not just to use 0 maybe also other values.
struct A
{
int a;
char b;
float c;
A(int _a=0,char _b=0,float _c=0.0) : a(_a), b(_b), c(_c) {}
};
int main()
{
A a;
// work with a
return 0;
}
There are several ways:
Use initializer mystruct x = { '\0', 0.0f, 0 };
Use mystruct x; memset(&x, 0, sizeof(x));
Write a function (or, in C++, a constructor) that sets each value to zero.
Generally, first one is the most obvious, but if you have a large number of structs, then you may find either of option 2 or 3 more suitable.
Note: using memset is ONLY safe on data structures that ONLY contain data. In C++, a struct and a class are almost identical, and a struct that has member functions, has other struct or class members or has inherited from another class or struct, will definitely not be safe to use memset on. And of course, this is particularly dangerous if you start out with a plain data struct, and then ADD functionality into the struct that "breaks" the 'only data' promise.
Edit: Just to be clear, the struct doesn't do anything, as in it has no functions. I think I gave the impression that I thought using an initialiser list and leaving the body of the constructor empty was the issue at hand.
Say I'm using a struct to hold two values, and I have a constructor just so I can create an arbitrary struct like this:
struct twoValues
{
int x;
int y;
twoValues(int x_, int y_):y(y_),x(x_)
{}
};
someFunction(twoValues(1,2));
That saves me from having to do this:
twoValues anInstance;
anInstance.x=1;
anInstance.y=2;
someFunction(anInstance);
Edit: You're all correct, I could also initialise with the following:
twoValues anInstance = {1,2};
I see nothing wrong with this but I had some feedback from a C++ test and one of the negative feedback marks was "constructors for structs that don't do anything". I had limited contact with the guy testing me and so never asked why.
Is it a bad thing and why? I would rather carry on doing it.
It depends on what the struct is being used for. As others have said,
the constructor means that the class is no longer a POD, and that
aggregate initialization cannot be used for it. In particular, you
cannot have something at namespace scope like:
TwoValues const table[] =
{
{ 1, 2 },
{ 3, 4 },
// ...
};
You can have:
TwoValues const table[] =
{
TwoValues( 1, 2 ),
TwoValues( 3, 4 ),
// ...
};
but it is more verbose, and it implies dynamic initialization, which may
result in order of initialization issues.
On the other hand, without the constructor, you cannot create temporary
instances on the fly. Instead of:
extern void f( TwoValues const& );
// ...
f( TwoValues( 1, 2 ) );
you have to write:
extern void f( TwoValues const& );
// ...
TwoValues tmp = { 1, 2 };
f( tmp );
If the object is dynamically allocated, it's even worse, since you
either have to allocate first, then initialize, or create a temporary as
above, and then write new TwoValues( tmp ) and use the implicit copy
constructor.
You have to choose. Depending on what the struct is used for, one or
the other will be preferred; on one hand, I have a lot of structs which
are used exclusively in static tables, and intentionally don't have a
constructor (and contain only types which support static
initialization), and use them a lot for configuring code. On the other
hand, I also have a lot of structs which are internal to a class, along
the lines of Node in a tree or a graph; these almost always have a
constructor, to facilitate creating them on the fly. There's no
"correct" answer without knowing the role of the struct in your
application.
Declaring an empty constructor has side-effects..
Even though your constructor has an empty body it is still considered to be a constructor, and therefore certain object properties will be lost - such as the object being POD.
Some cases require the use of Plain Old Data-types, which can make it undesirable to do what you've done without a specific reason.
Read more about initialization without a defult constructor in the next section.
c++03 && c++11
You can initialize your members with values without explicitly defining a "constructor that doesn't do anything", just use the brace-initialization syntax as in the below snippet.
struct Obj {
int x, y;
};
Obj a = {1,3}; /* a.x = 1, a.y = 2 */
c++03
The downside of not having a constructor is that you cannot initialize the object using = { ... } in certain circumstances when writing C++03.
C++11 fixes this for you, see the next section for relevant examples.
c++11
In C++11 the initialization using braces ( = { ... }) has been given increased functionality.
As seen in the below snippet where the defined constructor of Obj is called even though we use the same form of initialization as earlier in this post.
struct DoubleBoth {
DoubleBoth (int x, int y)
: x(x*2), y(y*2)
{}
int x, y;
};
The snippets below were all illegal prior to C++11:
DoubleBoth a = {1,2}; /* a.x = 2, a.y = 4 */
struct Wrapper {
Wrapper ()
: value {3,4}
{}
DoubleBoth value;
};
void func (DoubleBoth v = {1,2}) { // c++11 only
...
}
func ({4,5}); // c++11 only, c++03 requires `DoubleBoth obj (0,1); func (obj);`
It's much safer to have this kind of constructor, than to initialize with a list.
When you initialize with a list :
twoValues anInstance = {1, 2};
It really depends on the order of the members in the struct. Which in most cases is totaly random to begin with.
If another programmer happens to add another member, or to sort the members by alphabet, it wont work correctly.
Having a constructor that assigns the values to the right member by NAME is much safer.
You've stopped twoValues from being a POD and have prevented instances of the struct from being default- or value- initialized which are often desirable properties. Personally, I would prefer to have a free function for making temporary instances if you need a simple C++03 friendly approach.
E.g.
twoValues makeTwoValues(int x_, int y_)
{
twoValues tmp = { x_, y_ };
return tmp;
}
void f() {
someFunction(makeTwoValues(1,2));
}
E.g. initializing a member of type twoValues
class X {
twoValues tv;
public:
X(int x, int y) : tv(makeTwoValues(x, y)) {}
};
Probably because you can initialize it like this:
twoValues anInstance = {1, 2};
However, without the constructor you cannot initialize a anInstance in another struct's initializer list in C++03. For example:
struct Bar {
twoValues v_;
Bar() : v_(1,2) {} // error!
Bar() { v_ = {1,2}; } // have to assign value in constructor body
Bar() : v_{1,2} {} // OK in C++11
};
so in fact the constructor does something, and it does serve a very useful purpose in C++03. It is less of an issue in C++11.
There is nothing wrong with this contructor.
Also, it does something, it affect values to x and y, which is what I would expect from such a constructor.
But, maybe there are some coding rules in your company that says that you should do it another way. In that case I would recommend you ask the person that gave you the feedback and make the necessary modifications.
The constructor makes the struct a non-POD which may not be desirable in some cases.
If your struct doesn't have constructor, then your struct will be POD1, and you will be allowed to initialize like this:
twoValues anInstance = {1,2}; //C++03 and C++11 both!
twoValues anInstance {1,2}; //C++11 only
which are good.
1. Actually there are other things which make a struct non-POD. So just because your struct doesn't have constructor doesn't necessarily mean it is POD. You would like to see this post to know what those other things are.
Structures can have constructors, and the syntax is the same as for classes in C++. The difference between a class and a struct is that class-members are private by default, while struct-members default to public, however Unions will not allow constructors in the structs. You can make a constructor on the union though.
suppose we have a class
class Foo {
private:
int PARTS;
public:
Foo( Graph & );
int howBig();
}
int Foo::howBig() { return this->PARTS; }
int Foo::howBig() { return PARTS; }
Foo::Foo( Graph &G ) {
<Do something with G.*>
}
Which one of howBig()-variants is correct?
The &-sign ensures that only the reference for Graph object
is passed to initialization function?
In C I would simply do something like some_function( Graph *G ),
but in C++ we have both & and *-type variables, never understood
the difference...
Thank you.
When you've local variable inside a member function, then you must have to use this as:
Foo::MemberFunction(int a)
{
int b = a; //b is initialized with the parameter (which is a local variable)
int c = this->a; //c is initialized with member data a
this->a = a; //update the member data with the parameter
}
But when you don't have such cases, then this is implicit; you need to explicity write it, which means in your code, both versions of howBig is correct.
However, in member initialization list, the rules are different. For example:
struct A
{
int a;
A(int a) : a(a) {}
};
In this code, a(a) means, the member data a is being initialized with the parameter a. You don't have to write this->a(a). Just a(a) is enough. Understand this visually:
A(int a) : a ( a ) {}
// ^ ^
// | this is the parameter
// this is the member data
You can use this-> to resolve the dependent name issue without explicitly having to spell out the name of the base. If the name of the base is big this could arguably improve readability.
This issue only occurs when writing templates and using this-> is only appropriate if they're member functions, e.g.:
template <typename T>
struct bar {
void func();
};
template <typename T>
struct foo : public bar {
void derived()
{
func(); // error
this->func(); // fine
bar<T>::func(); // also fine, but potentially a lot more verbose
}
};
Which one of howBig()-variants is correct?
both in your case, the compiler will produce the same code
The &-sign ensures that only the reference for Graph object is passed to initialization function? In C I would simply do something like some_function( Graph *G ), but in C++ we have both & and *-type variables, never understood the difference...
there is no difference as per the use of the variable inside the method(except syntax) - in the case of reference(&) imagine as if you've been passed an invisible pointer that you can use without dereferencing
it(the &) might be "easier" for clients to use
Both forms of Foo::howBig() are correct. I tend to use the second in general, but there are situations that involve templates where the first is required.
The main difference between references and pointers is the lack of "null references". You can use reference arguments when you don't want to copy the whole object but you want to force the caller to pass one.
Both are correct. Usually shorter code is easier to read, so only use this-> if you need it to disambiguate (see the other answers) or if you would otherwise have trouble understanding where the symbol comes from.
References can't be rebound and can't be (easily) bound to NULL, so:
Prefer references to pointers where you can use them. Since they cannot be null and they cannot be deleted, you have fewer things to worry about when using code that uses references.
Use const references instead of values to pass objects that are large (more than say 16 or 20 bytes) or have complex copy constructors to save copy overhead while treating it as if it was pass by value.
Try to avoid return arguments altogether, whether by pointer or reference. Return complex object or std::pair or boost::tuple or std::tuple (C++11 or TR1 only) instead. It's more readable.
I'm having trouble figuring out which is better in C++:
I use a struct to manage clients in a message queue, the struct looks like this:
typedef struct _MsgClient {
int handle;
int message_class;
void *callback;
void *private_data;
int priority;
} MsgClient;
All of these being POD entities.
Now, I have an array of these structs where I store my clients (I use an array for memory constraints, I have to limit fragmentation). So in my class I have something like this:
class Foo
{
private:
MsgClient _clients[32];
public:
Foo()
{
memset(_clients, 0x0, sizeof(_clients));
}
}
Now, I read here and there on SO that using memset is bad in C++, and that I'd rather use a constructor for my structure.
I figured something like this:
typedef struct _MsgClient {
int handle;
int message_class;
void *callback;
void *private_data;
int priority;
// struct constructor
_MsgClient(): handle(0), message_class(0), callback(NULL), private_data(NULL), priority(0) {};
} MsgClient;
...would eliminate the need of the memset. But my fear is that when foo is initialized, the struct constructor will be called 32 times, instead of optimizing it as a simple zero out of the memory taken by the array.
What's your opinion on this?
I just found this: Can a member struct be zero-init from the constructor initializer list without calling memset? , is it appropriate in my case (which is different: I have an array, not a single instance of the structure)?
Also, according to this post, adding a constructor to my structure will automatically convert it into a non-POD structure, is it right?
On a conforming implementation, it's perfectly valid to value-initialize an array in the constructor initializer list with an empty member initializer. For your array members, this will have the effect of zero-initializing the members of each array element.
The compiler should be able to make this very efficient and there's no need for you to add a constructor to your struct.
E.g.
Foo() : _clients() {}
You can you memset freely even in C++, as long as you understand what you are doing.
About the performance - the only way to see which way is really faster is to build your program in release configuration, and then see in the disassembler the code generated.
Using memset sounds somewhat faster than per-object initialization. However there's a chance the compiler will generated the same code.
Instead of having to remember to initialize a simple 'C' structure, I might derive from it and zero it in the constructor like this:
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct()
{
memset(this, 0, sizeof(MY_STRUCT));
}
};
This trick is often used to initialize Win32 structures and can sometimes set the ubiquitous cbSize member.
Now, as long as there isn't a virtual function table for the memset call to destroy, is this a safe practice?
You can simply value-initialize the base, and all its members will be zero'ed out. This is guaranteed
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct():MY_STRUCT() { }
};
For this to work, there should be no user declared constructor in the base class, like in your example.
No nasty memset for that. It's not guaranteed that memset works in your code, even though it should work in practice.
PREAMBLE:
While my answer is still Ok, I find litb's answer quite superior to mine because:
It teaches me a trick that I did not know (litb's answers usually have this effect, but this is the first time I write it down)
It answers exactly the question (that is, initializing the original struct's part to zero)
So please, consider litb's answer before mine. In fact, I suggest the question's author to consider litb's answer as the right one.
Original answer
Putting a true object (i.e. std::string) etc. inside will break, because the true object will be initialized before the memset, and then, overwritten by zeroes.
Using the initialization list doesn't work for g++ (I'm surprised...). Initialize it instead in the CMyStruct constructor body. It will be C++ friendly:
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct() { n1 = 0 ; n2 = 0 ; }
};
P.S.: I assumed you did have no control over MY_STRUCT, of course. With control, you would have added the constructor directly inside MY_STRUCT and forgotten about inheritance. Note that you can add non-virtual methods to a C-like struct, and still have it behave as a struct.
EDIT: Added missing parenthesis, after Lou Franco's comment. Thanks!
EDIT 2 : I tried the code on g++, and for some reason, using the initialization list does not work. I corrected the code using the body constructor. The solution is still valid, though.
Please reevaluate my post, as the original code was changed (see changelog for more info).
EDIT 3 : After reading Rob's comment, I guess he has a point worthy of discussion: "Agreed, but this could be an enormous Win32 structure which may change with a new SDK, so a memset is future proof."
I disagree: Knowing Microsoft, it won't change because of their need for perfect backward compatibility. They will create instead an extended MY_STRUCTEx struct with the same initial layout as MY_STRUCT, with additionnal members at the end, and recognizable through a "size" member variable like the struct used for a RegisterWindow, IIRC.
So the only valid point remaining from Rob's comment is the "enormous" struct. In this case, perhaps a memset is more convenient, but you will have to make MY_STRUCT a variable member of CMyStruct instead of inheriting from it.
I see another hack, but I guess this would break because of possible struct alignment problem.
EDIT 4: Please take a look at Frank Krueger's solution. I can't promise it's portable (I guess it is), but it is still interesting from a technical viewpoint because it shows one case where, in C++, the "this" pointer "address" moves from its base class to its inherited class.
Much better than a memset, you can use this little trick instead:
MY_STRUCT foo = { 0 };
This will initialize all members to 0 (or their default value iirc), no need to specifiy a value for each.
This would make me feel much safer as it should work even if there is a vtable (or the compiler will scream).
memset(static_cast<MY_STRUCT*>(this), 0, sizeof(MY_STRUCT));
I'm sure your solution will work, but I doubt there are any guarantees to be made when mixing memset and classes.
This is a perfect example of porting a C idiom to C++ (and why it might not always work...)
The problem you will have with using memset is that in C++, a struct and a class are exactly the same thing except that by default, a struct has public visibility and a class has private visibility.
Thus, what if later on, some well meaning programmer changes MY_STRUCT like so:
struct MY_STRUCT
{
int n1;
int n2;
// Provide a default implementation...
virtual int add() {return n1 + n2;}
};
By adding that single function, your memset might now cause havoc.
There is a detailed discussion in comp.lang.c+
The examples have "unspecified behaviour".
For a non-POD, the order by which the compiler lays out an object (all bases classes and members) is unspecified (ISO C++ 10/3). Consider the following:
struct A {
int i;
};
class B : public A { // 'B' is not a POD
public:
B ();
private:
int j;
};
This can be laid out as:
[ int i ][ int j ]
Or as:
[ int j ][ int i ]
Therefore, using memset directly on the address of 'this' is very much unspecified behaviour. One of the answers above, at first glance looks to be safer:
memset(static_cast<MY_STRUCT*>(this), 0, sizeof(MY_STRUCT));
I believe, however, that strictly speaking this too results in unspecified behaviour. I cannot find the normative text, however the note in 10/5 says: "A base class subobject may have a layout (3.7) different from the layout of a most derived object of the same type".
As a result, I compiler could perform space optimizations with the different members:
struct A {
char c1;
};
struct B {
char c2;
char c3;
char c4;
int i;
};
class C : public A, public B
{
public:
C ()
: c1 (10);
{
memset(static_cast<B*>(this), 0, sizeof(B));
}
};
Can be laid out as:
[ char c1 ] [ char c2, char c3, char c4, int i ]
On a 32 bit system, due to alighments etc. for 'B', sizeof(B) will most likely be 8 bytes. However, sizeof(C) can also be '8' bytes if the compiler packs the data members. Therefore the call to memset might overwrite the value given to 'c1'.
Precise layout of a class or structure is not guaranteed in C++, which is why you should not make assumptions about the size of it from the outside (that means if you're not a compiler).
Probably it works, until you find a compiler on which it doesn't, or you throw some vtable into the mix.
If you already have a constructor, why not just initialize it there with n1=0; n2=0; -- that's certainly the more normal way.
Edit: Actually, as paercebal has shown, ctor initialization is even better.
My opinion is no. I'm not sure what it gains either.
As your definition of CMyStruct changes and you add/delete members, this can lead to bugs. Easily.
Create a constructor for CMyStruct that takes a MyStruct has a parameter.
CMyStruct::CMyStruct(MyStruct &)
Or something of that sought. You can then initialize a public or private 'MyStruct' member.
From an ISO C++ viewpoint, there are two issues:
(1) Is the object a POD? The acronym stands for Plain Old Data, and the standard enumerates what you can't have in a POD (Wikipedia has a good summary). If it's not a POD, you can't memset it.
(2) Are there members for which all-bits-zero is invalid ? On Windows and Unix, the NULL pointer is all bits zero; it need not be. Floating point 0 has all bits zero in IEEE754, which is quite common, and on x86.
Frank Kruegers tip addresses your concerns by restricting the memset to the POD base of the non-POD class.
Try this - overload new.
EDIT: I should add - This is safe because the memory is zeroed before any constructors are called. Big flaw - only works if object is dynamically allocated.
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct()
{
// whatever
}
void* new(size_t size)
{
// dangerous
return memset(malloc(size),0,size);
// better
if (void *p = malloc(size))
{
return (memset(p, 0, size));
}
else
{
throw bad_alloc();
}
}
void delete(void *p, size_t size)
{
free(p);
}
};
If MY_STRUCT is your code, and you are happy using a C++ compiler, you can put the constructor there without wrapping in a class:
struct MY_STRUCT
{
int n1;
int n2;
MY_STRUCT(): n1(0), n2(0) {}
};
I'm not sure about efficiency, but I hate doing tricks when you haven't proved efficiency is needed.
Comment on litb's answer (seems I'm not yet allowed to comment directly):
Even with this nice C++-style solution you have to be very careful that you don't apply this naively to a struct containing a non-POD member.
Some compilers then don't initialize correctly anymore.
See this answer to a similar question.
I personally had the bad experience on VC2008 with an additional std::string.
What I do is use aggregate initialization, but only specifying initializers for members I care about, e.g:
STARTUPINFO si = {
sizeof si, /*cb*/
0, /*lpReserved*/
0, /*lpDesktop*/
"my window" /*lpTitle*/
};
The remaining members will be initialized to zeros of the appropriate type (as in Drealmer's post). Here, you are trusting Microsoft not to gratuitously break compatibility by adding new structure members in the middle (a reasonable assumption). This solution strikes me as optimal - one statement, no classes, no memset, no assumptions about the internal representation of floating point zero or null pointers.
I think the hacks involving inheritance are horrible style. Public inheritance means IS-A to most readers. Note also that you're inheriting from a class which isn't designed to be a base. As there's no virtual destructor, clients who delete a derived class instance through a pointer to base will invoke undefined behaviour.
I assume the structure is provided to you and cannot be modified. If you can change the structure, then the obvious solution is adding a constructor.
Don't over engineer your code with C++ wrappers when all you want is a simple macro to initialise your structure.
#include <stdio.h>
#define MY_STRUCT(x) MY_STRUCT x = {0}
struct MY_STRUCT
{
int n1;
int n2;
};
int main(int argc, char *argv[])
{
MY_STRUCT(s);
printf("n1(%d),n2(%d)\n", s.n1, s.n2);
return 0;
}
It's a bit of code, but it's reusable; include it once and it should work for any POD. You can pass an instance of this class to any function expecting a MY_STRUCT, or use the GetPointer function to pass it into a function that will modify the structure.
template <typename STR>
class CStructWrapper
{
private:
STR MyStruct;
public:
CStructWrapper() { STR temp = {}; MyStruct = temp;}
CStructWrapper(const STR &myStruct) : MyStruct(myStruct) {}
operator STR &() { return MyStruct; }
operator const STR &() const { return MyStruct; }
STR *GetPointer() { return &MyStruct; }
};
CStructWrapper<MY_STRUCT> myStruct;
CStructWrapper<ANOTHER_STRUCT> anotherStruct;
This way, you don't have to worry about whether NULLs are all 0, or floating point representations. As long as STR is a simple aggregate type, things will work. When STR is not a simple aggregate type, you'll get a compile-time error, so you won't have to worry about accidentally misusing this. Also, if the type contains something more complex, as long as it has a default constructor, you're ok:
struct MY_STRUCT2
{
int n1;
std::string s1;
};
CStructWrapper<MY_STRUCT2> myStruct2; // n1 is set to 0, s1 is set to "";
On the downside, it's slower since you're making an extra temporary copy, and the compiler will assign each member to 0 individually, instead of one memset.