typedef struct foo
{
bool my_bool;
int my_int;
} foo;
In the example above I understand that my_bool will be initialized randomly to either true or false but what about my_int? I assumed that my_int would be default initialized to 0 but that seems not to be the case.
Defining structs in this way appears to be incompatible with initialization lists so what is the best way to initialize my_bool and my_int to false and 0 respectively?
Types don't get "initialized". Only objects of some type get initialized. How and when they get initialized depends on how and where the corresponding object is defined. You provided no definition of any object in your question, so your question by itself doesn't really make much sense - it lacks necessary context.
For example, if you define a static object of type foo
static foo foo_object; // zeros
it will be automatically zero-initialized because all objects with static duration are always automatically zero-initialized.
If you define an automatic object of type foo without an initializer, it will remain uninitialized
void func()
{
foo foo_object; // garbage
}
If you define an automatic object of type foo with an aggregate initializer, it will be initialized in accordance with that initializer
void func()
{
foo foo_object1 = { 1, 2 }; // initialized
foo foo_object2 = {}; // initialized with zeros
}
If you allocate your object with new and provide no initializer, it will remain uninitialized
foo *p = new foo; // garbage in `*p`
But if you use the () initializer, it will be zero-initialzed
foo *p = new foo(); // zeros in `*p`
If you create a temporary object of type foo using the foo() expression, the result of that expression will be zero-initialized
bool b = foo().my_bool; // zero
int i = foo().my_int; // zero
So, once again, in your specific case the initialization details depend on now you create the object of your type, not on your type itself. Your type itself has no inherent initialization facilities and doesn't interfere with the initialization in any way.
Implement a default constructor:
typedef struct foo
{
foo()
: my_bool(false), my_int(0)
{
// Do nothing
}
bool my_bool;
int my_int;
} foo;
First off, the way that struct is declared is in the style of C. In C++ you should just do:
struct foo
{
bool my_bool;
int my_int;
};
In both C and C++, initialization is a separate step from allocation. If you always want to initialize the members of your struct, use default initialization syntax like this:
struct foo
{
bool my_bool{};
bool my_int{};
};
In older versions of C++ you need to manually write a default constructor that initializes all the members (the newer syntax above is just sugar for this):
struct foo
{
foo() : my_bool(), my_int() { }
bool my_bool;
int my_int;
};
As #sbi notes, if you want to manually initialize the struct, even without the default constructor, you can do foo myFoo = foo();
Have a default constructor:
struct foo {
foo() : my_bool(false), my_int(0) {}
bool my_bool;
int my_int;
};
You are not creating any object in that code. Initialization is done when you create objects, and is not particularly tucked by the way you declare the struct.
For instance the following initializes the boolean to false and the integer to 0
foo f = { };
Notice that you have just typdefed your struct. You have not created an object. Like others said you can omit the typedef in C++ and just declare the struct, and you are still able to refer to the type by just saying foo.
If you omit explicit initialization when you define an object, then for sure no initialization is done unless the object is defined at namespace scope or defined as static locally (in which case all members are zero-initialized) or the class has a user defined default constructor that does initialization accordingly.
As long as you are declaring the structs in a C-way, you could use zeromemory to null exactly sizeof(foo) bytes, therefore defaulting all values to 0.
In C++, you could define your structure with a constructor which would set your values to some default values if needed.
c and c++ don't initialize variables at all. They contain whatever happened to be in the memory location that they're now in previously. This also applies for member variables in classes and structs unless you specifically initialize them to a value.
Related
I need to do something like
class foo {
foo();
int a[];
}
Further in cpp-file:
foo::foo() : a{1,2,3,4} {}
Peculiarities:
C++98 standard
array is not int, initializing list is much longer. Though its values are known at compile time, they can change from time to time
EDIT: Another option is also suitable, when new[] is used for memory allocation, but, again, it is undesirable to state the array size explicitly:
class foo {
foo();
int * a;
}
Further in cpp-file:
foo::foo() {
a = new[]; // impossible
// filling the array with values
}
You cannot do that: The size of the array is part of the type of the array, and hence of the class. The constructor is also part of the class. The class needs to exist first before you can call constructors, so the constructor call cannot influence the class definition.
given a struct in the form ( declared before the main() or after )
struct
{
...
} bar;
I don't know how to manage this and how to treat this kind of object.
In general I would like a 360° answer about this but I also have few questions:
is this equivalent to declaring a static struct ?
it's legal and safe in C++11 ?
how to access bar by reference ?
For the last one I have prepared a small snippet here, that doesn't works but shows what I'm trying to achieve.
It's global object of unnamed struct. You cannot use this type as argument to function (since you doesn't know real type of the object). You can use decltype for this, but it doesn't needed since it's global object. It's legal and safe.
#include <iostream>
struct
{
double k1 = 0.123;
} bar;
int foo(decltype(bar)& a)
{
return a.k1-1;
};
int main()
{
std::cout << foo(bar) << std::endl;
return(0);
}
example
Really, since you have only one global object of this struct - you simply can use
#include <iostream>
struct
{
double k1 = 0.123;
} bar;
int foo()
{
return bar.k1-1;
};
int main()
{
std::cout << foo() << std::endl;
return(0);
}
This is simply a global variable. You can access it from any function or method in this compilation unit. The correct way of declaring it (in regard to your snippet) would be:
struct foo
{
double k = 1.23;
};
foo bar;
Now you can simply pass it by reference like this:
void f(foo & b)
{
b.k = 34.5;
}
In your snippet, bar is a variable of type being an unnamed struct:
struct <unnamed>
{
double k = 1.23;
} bar;
Since you did not give any name to your type, you're unable to pass it as a parameter to functions in the classic way. C++11 allows you to do so using the decltype directive:
struct
{
double k = 1.23;
} bar;
void f(decltype(bar) & b)
{
b.k = 3.45;
}
As for your questions:
It is not the same as a static struct. Static variables behave in a little different way. Static classes (= structs) too.
It is legal and safe to use global variables in C++11, but it is strongly advised not to use them, because they may easily break program's logic or architecture. Instead, one should use static classes or singletons.
No. static is a storage attribute. A struct is like any other data type: it can be static, volatile, auto, extern, and others defined by some implementations.
It is legal and safe.
Reference such a structure like this:
struct {
int field1, field2;
double yada, yada2, yada3;
} bar1, bar2;
bar1.yada3 = 3.14159265358979; // assign a field in the struct
bar2 = bar1; // copy contents of bar1 to bar2
1> bar is only single instance of its type. You can not have another instance of same type as bar. Its type is unnamed type struct, just like anonymous union. It is legal to have one such. It is more like global static(but not it is not static) just because you cannot refer it by extern keyword in other file.Any hack you have to refer it in other file ...?
3> It is legal to have it.
4> You can not declare reference to variable whose type you do not know. .Although u can access/modify same object anywhere in the file, so no need of reference. References are used to remove * and -> from code, mainly, otherwise what references do, is all possible with pointer.
is this equivalent to declaring a static struct ?
No, you'd use the static keyword for that, as for any other static variable. It's declaring a global variable, i.e. with static storage duration and external linkage, equivalent to:
struct Bar {...};
Bar bar;
it's legal and safe in C++11 ?
Yes.
how to access bar by reference ?
Since the type has no name, it has to be inferred, either by template argument deduction or, in C++11:
auto & ref = bar;
template <typename Bar> void bar_by_ref(Bar & bar) {
/* do something with bar */
}
Alternatively, in C++11, the type can be extracted by decltype:
decltype(bar) & ref = bar;
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.
I have a custom class that I want to behave like a built-in type.
However I have noticed that you can initialise a const variable of that class without providing an initial value. My class currently has an empty default constructor.
Here is a comparison of int and my class foo:
int a; // Valid
int a = 1; // Valid
const int a = 1; // Valid
const int a; // Error
foo a; // Valid
foo a = 1; // Valid
const foo a = 1; // Valid
const foo a; // Should cause an error, but it compiles
As you can see I need to prevent
const foo a;
from compiling.
Any ideas from C++ gurus?
It compiles only if it has a default constructor, and it compiles because it has it, which means that it is initialized. If you don't want that line to compile, just disable the default constructor (will also make foo a; an error as an unwanted side effect). Without a definition of foo or what you want to do, this is as far as I can get.
I don't think there is any way of achieving what you want (i.e. allow the non-const variable to be default initialized, while having the const version fail compilation and allowing the other use cases --that require providing constructors)
The rules of C++ simply say that default-initialization (e.g. new T;) and value-initialization (e.g. new T();) are the same for objects of class type, but not for objects of fundamental type.
There's nothing you can do to "override" this distinction. It's a fundamental part of the grammar. If your class is value-initializable, then it is also default-initializable.
There is a sort-of exception for classes without any user-defined constructors: In that case, initialization of members is done recursively (so if you default-init the object, it tries to default-init all members), and this will fail if any of the class members are themselves fundamental, or again of this nature.
For example, consider the following two classes:
struct Foo { int a; int b; };
struct Goo { int a; int b; Goo(){} };
//const Foo x; // error
const Goo y; // OK
The implicit constructor for Foo is rejected because it doesn't initialize the fundamental members. However, y is happily default-initialized, and y.a and y.b are now "intentionally left blank".
But unless your class doesn't have any user-defined constructors, this information won't help you. You cannot "forward" the initialization type to a member (like Foo() : INIT_SAME_AS_SELF(a), b() { }).
How would you call the constructor of the following class in these three situations: Global objects, arrays of objects, and objects contained in another class/struct?
The class with the constructor (used in all three examples):
class Foo {
public:
Foo(int a) { b = a; }
private:
int b;
};
And here are my attempts at calling this constructor:
Global objects
Foo global_foo(3); // works, but I can't control when the constructor is called.
int main() {
// ...
}
Arrays of objects
int main() {
// Array on stack
Foo array_of_foos[30](3); // doesn't work
// Array on heap
Foo *pointer_to_another_array = new Foo(3) [30]; // doesn't work
}
There I'm attempting to call the constructor for all elements of the arrays, but I'd also like to know how to call it on individual elements.
Objects contained in classes/structs
class Bar {
Foo foo(3); // doesn't work
};
int main() {
Bar bar;
}
Global objects
Yours is the only way. On the other hand, try to avoid this. It’s better to use functions (or even other objects) as factories instead. That way, you can control the time of creation.
Arrays of objects
There’s no way to do this directly. Non-POD objects will always be default-constructed. std::fill is often a great help. You might also want to look into allocators and std::uninitialized_fill.
Objects contained in classes/structs
Use initialization lists in your constructor:
class Bar {
Foo foo;
Bar() : foo(3) { }
};
Static members must actually be defined outside the class:
class Bar {
static Foo foo;
};
Foo Bar::foo(3);
To correct some misconceptions about globals:
The order is well defined within a compilation unit.
It is the same as the order of definition
The order across compilation units is undefined.
The order of destruction is the EXACT opposite of creation.
Not something I recommend but: So a simple solution is to to put all globals into a single compilation unit.
Alternatively you can tweak the use of function static variables.
Basically you can have a function the returns a reference to the global you want (defining the global inside the function). It will be created on first use (and destroyed in reverse order of creation).
Foo& getGlobalA() // passed parameters can be passed to constructor
{
static Foo A;
return A;
}
Foo& getGlobalB()
{
static Foo B;
return B;
}
etc.
The Konrad reply is OK, just a puntualization about the arrays....
There is a way to create an array of items(not pointers) and here it follows:
//allocate raw memory for our array
void *rawMemory = operator new[](30 * sizeof(Foo))
// point array_of_foos to this memory so we can use it as an array of Foo
Foo *array_of_foos = static_cast<Foo *>(rawMemory);
// and now we can create the array of objects(NOT pointers to the objects)
// using the buffered new operator
for (int i = 0; i < 30; i++)
new(array_of_foos[i])Foo(3);
This approach is described here: http://www.amazon.com/gp/product/0321334876?ie=UTF8&tag=aristeia.com-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321334876
For the global case there is no way to control when it is called. The C++ spec essentially says it will be called before main() and will be destroyed sometime afterwards. Other than that' the compiler is free to do as it pleases.
In the first array case you are creating a static array of Foo objects. By default each value in the array will be initialized with the default constructor of Foo(). There is no way with a raw C++ array to force a particular overloaded constructor to be called. You can infer a bit of control by switching to a vector instead of an array. The vector constructor has an overloaded constructor vector(size,defaultValue) which should achieve what you are looking for. But in this case you must be careful because instead of calling Foo(3) it will call Foo(const Foo& other) where other is Foo(3).
The second array case is very similar to the first case. The only real difference is where the memory is allocated (on the heap instead of the stack). It has the same limitation with regards to calling to the constructor.
The contained case is a different issue. C++ has a clear separation between the definition of a field within an object and the initialization of the field. To get this to work in C++ you'll need to change your Bar definition to the following
class Bar{
Foo foo;
Bar() : foo(3){}
};
There seems to be the general gist in this thread that you cannot initialize members of an array other than using the default constructor. One answer even creates another type, just to call another constructor. Even though you can (if the array is not part as a member of a class!):
struct foo {
foo(int a): a(a) { }
explicit foo(std::string s): s(s) { }
private:
int a;
std::string s;
};
/* global */
foo f[] = { foo("global"), foo("array") };
int main() {
/* local */
foo f[] = { 10, 20, 30, foo("a"), foo("b") };
}
The type, however, needs to be copy-able: The items given are copy-initialized into the members of the array.
For arrays as members in classes, it's the best to use containers currently:
struct bar {
/* create a vector of 100 foo's, initialized with "initial" */
bar(): f(100, foo("initial")) { }
private:
std::vector<foo> f;
};
Using the placement-new technique described by andy.gurin is an option too. But note it will complicate things. You will have to call destructors yourself. And if any constructor throws, while you are still building up the array, then you need to figure where you stopped... Altogether, if you want to have arrays in your class, and want to initialize them, use of a std::vector is a simple bet.
Construction of arrays of objects:
You can modify your original example by using default parameters.
Currently only the default constructor is supported.
This is something that is being addressed by the next version (because everybody asks this question)
C++0X initializer lists solve this problem for the arrays of objects case. See this Herb Sutter blog entry, where he describes them in detail.
In the meantime you might be able to work around the problem like so:
class Foo {
public:
Foo(int a) : b(a) {}
private:
int b;
};
class Foo_3 : public Foo {
public:
Foo_3() : Foo(3) {}
};
Foo_3 array_of_foos[30];
Here, the Foo_3 class exists solely for the purpose of calling the Foo constructor with the correct argument. You could make it a template even:
template <int i>
class Foo_n : public Foo {
public:
Foo_n() : Foo(i) {}
};
Foo_n<3> array_of_foos[30];
Again this might not do exactly what you want but may provide some food for thought.
(Also note that in your Foo class you really should get into the habit of using member initializer lists instead of assignments in the constructor, as per my example above)
I reckon there are two ways to make sure global class objects' constructors are called safely at the time of their "creation":
Declare them in a namespace and make that namespace globally accessible.
Make it a global pointer to the class object and assign a new class object to it in main(), granted code for other global objects' constructors that access the object will execute before this.
Just my two cents.