how to set everything inside a structure to 0? - c++

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.

Related

Is it safe to `reinterpret_cast` two unrelated vector of objects when those objects have the same binary representation?

I have newtypes around int, as well as classes that contains those newtype.
class IndexA {
int i;
};
class A {
IndexA index;
};
// this mimic exactly the hierarchy of `A`
struct IndexB {
int i;
};
struct B {
IndexB index;
};
Given that A and B share the exact same binary layout, does the following code contains undefined behavior or is it safe?
std::vector<A> vfoo {...};
std::vector<B> vbar {
std::move(
reinterpret_cast<std::vector<B>&>(vfoo)
)
};
I would have liked to be able to do a zero copy move transformation from std::vector<A> to std::vector<B>. Is it possible?
In my code:
A and B are really just a wrapper around int, so they have exactly the same binary representation.
The struct A only contains a mix of IndexA, std::optional<IndexA>, std::variant<IndexA, other types like IndexA>, or std::vector<IndexA or std::optional<IndexA>, …>. I think that I can assume that they have the same representation.
B is a strict copy of A, where every instances of IndexA are replaced by IndexB. The fields order is kept.
Is it safe to reinterpret_cast two unrelated vector of objects when those objects have the same binary representation?
No, it is not safe. The behaviour of the example program is undefined.
I would have liked to be able to do a zero copy move transformation from std::vector<A> to std::vector<B>. Is it possible?
No, it is not possible.
Something that you can do and is somewhat close to what you're trying is to have a vector of union of those types:
union IndexAB {
IndexA A;
IndexB B;
};
std::vector<IndexAB> vfoo {...};
for (IndexAB& u : vfoo) {
std::cout << u.A.i;
u.B.i = 42;
}
Whether A or B union member were activated doesn't matter. We can access either member regardless.
Note that this doesn't apply to all unions in general, but only in this particular case of standard layout structs, and specifically the members within their common initial sequence.
The standard does not allow you to convert between pointers of unrelated types, regardless of their binary layout:
struct A{ int i; };
struct B{ int i; };
B b{};
A* pa = reinterpret_cast<A*>(&b);
pa->i = 42; // undefined behavior

How to initialize a struct with enum member?

I have a struct with many members and with different types (it's like 20 members):
enum TheEnum
{
FIRST = 0,
SECOND,
...
}
struct TheStruct
{
TheEnum z; // <--- the point !!! note that this is the first member (edited)
int a;
int b;
char c[32];
...
}
Due to there is an enum type member, I cant just declare like:
TheStruct Object = {0};
It will give compile error, but this initialization is the best way in my opinion.
The other ways that I can think of is:
1. ZeroMemory it, but I dont like this one.
2. Write a constructor, but this needs a lot of work.
3. Just don't initialize it.
So, is there any way to solve the enum problem? Should I pick a way in these 3?
Thanks!
EDIT:
My big mistake, the error only occurs when TheEnum presents as the first member.
Compiled using vs2008 and as C++ code.
The error is C2440. http://msdn.microsoft.com/en-us/library/sy5tsf8z%28v=VS.80%29.aspx
[edit] as the question changed
If you initialize a struct, you have to provide the correct types in your initializer.
In your case, the correct initialization would look like this:
TheStruct Object = {FIRST};
Your initialization list initializes the given number of struct members with what you have written and the rest of the struct with '0'.
Since your first member is an enum, you have to initialize that enum in this case.
[/edit]
there is nothing necessary. if you're compiling in C and not C++ just don't forget to write enum and struct and everything should work...
enum TheEnum
{
FIRST = 0,
SECOND,
...
}
struct TheStruct
{
int a;
int b;
char c[32];
...
enum TheEnum z; // <--- the point !!!
}
struct TheStruct Object = {0};
You can initialize the enum member just like any other. For example: TheStruct temp = {0,0,"", FIRST};

Constructors for structs that don't do anything

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.

passing structure directly to function

I have a struct that I initialize like this:
typedef struct
{
word w;
long v;
}
MyStruct;
MyStruct sx = {0,0};
Update(sx);
Now, it seems such a waste to first declare it and then to pass it. I know that in C#, there's a way to do everything in one line. Is there any possiblity of passing it in a more clever (read: cleaner) way to my update function?
In C++, structs are the same as classes except in structs everything is public by default. So you can give a struct a constructor, e.g.
struct MyStruct
{
word w;
long v;
MyStruct(word w, long v) : w(w), v(v) {}
};
Update(MyStruct(0,0));
Also, C-style struct typedef'ing is unnecessary and discouraged in C++.
It depends on how your Update is declared. If it expects a value of MyStruct type or a reference of const MyStruct& type, you can just do
Update(MyStruct());
This is possible because you wanted to initialize your object with zeroes (which is what the () initializer will do in this case). If you needed different (non-zero) initializer values, you have to either provide a constructor for MyStruct or do it the way you do it in your question (at least in the current version of the C++ language).

memset for initialization in C++

memset is sometimes used to initialize data in a constructor like the example below. Does it work in general ? Is it a good idea in general?
class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};
A::A()
{
memset(this, 0, sizeof(*this));
}
Don't use memset. It's a holdover from C and won't work on non-PODs. Specifically, using it on a derived class that contains any virtual functions -- or any class containing a non-builtin -- will result in disaster.
C++ provides a specific syntax for initialization:
class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};
A::A()
: a(0), f(0), str(), lp(NULL)
{
}
To be honest, I'm not sure, but memset might also be a bad idea on floating-points since their format is unspecified.
It's a terrible idea. You're just tromping over data, paying no heed to how objects should be initialized. If your class is virtual, you're likely to wipe out the vtable pointer as well.
memset works on raw data, but C++ isn't about raw data. C++ creates abstractions, so if you want to be safe you use those abstractions. Use the initializer list to initialize members.
You can do it to POD types:
struct nothing_fancy_here
{
bool b;
int i;
void* p;
};
nothing_fancy_here x;
memset(&x, 0, sizeof(x));
But if you're doing it on this, that means you're in a user-defined constructor and no longer qualify as a POD type. (Though if all your members are POD it might work, as long as none contain 0 as a trap value. I'm sure not sure if any other sources of undefined behavior come into play here.)