Function Pointer Array Initialization - c++

Consider an array of function pointers within a class in c++14:
class myClass {
myClass();
void (* myFunctions [5])();
}
This array will be populated in other parts of the code, and it is not guaranteed that the array will actually hold as many function pointers as it can (5 in the example). So before calling any of the functions referred to by the array i'd need to check whether the pointer I'm trying to use actually stores something. My idea was to compare the pointer against nullptr, and assume that it points to a valid function if the test fails, i.e. in some function of that class:
if(myFunctions[x] == nullptr) {
// Handle error
return;
}
// Use myFunctions[x]
I was wondering if I need to initialize the array before making that kind of speculation. How is this array initialized if I only write the above two lines of code? Can I assume something like myFunctions[x] == nullptr is true in that case? Or do I need to do an explicit initialization like the following one?
for(int i = 0; i < dimension; i++)
myFunctions[i] = nullptr;
I've found the zero initialization page on cppreference.com, but as I'm learning c++ and I'm still very unexperienced I wasn't able to understand whether this applies in my case. I've also tried to test the pointers by printing their value without assigning any function address and got 0 0 0 0 0, but I don't think the result is reliable: this program is for a microcontroller, and it's possible that the "garbage" values on the stack are all 0s since it is emptied during each code upload.

I don't think that you have to initialize the array, although I'd encourage you to do that. The reason why the array is default-initialized in your case is because you provide a constructor and do not mention the data member in the initializer list (cf. cppreference/default initialization):
Default initialization is performed in three situations:
...
3) when a base class or a non-static data member is not mentioned in a
constructor initializer list and that constructor is called.
Hence, default initialization will take place.
Anyway, in order to express that you rely on a data member to be "zero" without enforcing in other ways that non-initialized entries will not be accessed, I'd make the initialization explicit, e.g.
class myClass {
myClass();
void (* myFunctions [5])() = { };
}

Related

Accessing a Class Function when the Class instance is within a Struct

I have an array of structs -
struct MagicalUnicornBullets {
PS2Sprite SparklyUnicornBullet();
bool onscreen;
};
MagicalUnicornBullets MagicalUnicornBullets[25];
I want to loop through the array, and initialise the contents of the struct.
Obviously, this is just the case of a for loop, and for the bool it's simply onscreen = false; but how would I initialise the SparklyUnicornBullet?
Right now my code is -
MagicalUnicornBullets[i].SparklyUnicornBullet.ScaleAbsolute(4,4);
I'm well aware this is wrong - but how do I access the class functions when they're within the Struct?
Realize that SparklyUnicornBullet is actually a member function which returns a PS2Sprite object. This returned PS2Sprite has a member function ScaleAbsolute which you want to call. So your code above is nearly correct. You are simply missing ()'s:
MagicalUnicornBullets[i].SparklyUnicornBullet().ScaleAbsolute(4,4);
That said, there's a number of things that's bad with your code. For one, you are declaring an array that has the same name as an object:
MagicalUnicornBullets MagicalUnicornBullets[25];
I think this is allowed, but it is so evil and malmotivated that I can't even say that for certian, because I would reject any such code regardless of it's motivation or legality. You should give the array a different name:
MagicalUnicornBullets bullets[25];
Next, your initialization loop is unneeded. The code:
MagicalUnicornBullets MagicalUnicornBullets[25];
creates a C-style array of 25 MagicalUnicornBullets by calling each one's default constructor. So the easiest thing to do is to simply provide a default constructor that does what you want:
struct MagicalUnicornBullets {
MagicalUnicornBullets();
// ...
};
MagicalUnicornBullets::MagicalUnicornBullets()
: onscreen(false)
{
SparklyUnicornBullet().ScaleAbsolute(4,4)
}
Now there's no need for a loop at all. All 25 will be constructed and initialized the way you want.
Finally, usually in C++ it's advantagerous to not use a C-style array at all, but a collection class such as std::vector.

Strange constructor

Well, I'm gonna be pretty straightforward here, I just have a piece of code in c++ which I'm not sure I really understand and need some help with.
Ok, to simplify lets just say I have a class that is defined like this: (the real class is a little bit more complicated, but this is what matters)
class myClass : public Runnable {
Semaphore *m_pMySemaphore;
__Queue<Requests> *m_pQueue;
Request m_Request;
VetorSlotBuffer *m_vetorSlotBuffer;
}
Up to here nothing is wrong, myClass is just a regular class which has 3 members that actually are pointers to other classes and an object of the class Request, the implementation of those classes not being important for my point here.
Then when this person implemented the constructor for myClass he or she did this:
myClass::myClass() : m_pMySemaphore(0), m_pQueue(0), m_vetorSlotBuffer(0) {
}
It's pretty evident that those three variables are treated like that by the constructor because they are pointers, am I right? but what kind of syntax is that? am I setting the pointers to null by doing that? I've seen a little bit of c++ already but never found something like that.
And secondly, what's the deal with the ":" after the constructor declaration? that I've seen but never took the time to investigate. Is this like an inner class or something?
Thank you very much in advance.
Nelson R. Perez
This is an initialization list
And it's the recommended way to initialize your members
It's member's initialization on object creation, called initialization list.
You can't initialize them elsewhere, say:
class X {
int i = 0; // error bad syntax
}
Neither in constructor by use of assignment, if they're const :
class X {
const int i;
X(){
i = 0; // error it's a const
}
}
So the c++ guys made up that syntax!
Yes, those pointers are being initialized to NULL. The key thing here is that they are initialized, as opposed to assigned. I.e.:
myClass::myClass()
: m_pMySemaphore(0), // initialized to 0
m_pQueue(NULL) // initialized to NULL (preferable to 0)
// no initializer for m_Request - uses default constructor
// no initializer for m_vectorSlotBuffer
{
// at this point, the object is entirely initialized, and can be used.
// this next line ASSIGNS to the member
m_vectorSlotBuffer = 0;
}
What happens to m_vectorSlotBuffer, is that it is initialized, and then assigned, in two separate steps. By doing it like m_pQueue, we save a step, and initialize properly. This becomes very important when we want to use non-default constructor, or if we want to initialize const members.
Also, the : after the constructor () is what begins the initialization section, before we get to the { where we enter the body of the constructor.
Finally, NULL is not guaranteed to be 0. NULL is portable, but most architectures use 0 as NULL.
EDIT: 0/NULL distinction is not meaningful anymore. Just pick one and be consistent.
Yes, pointers set to 0 are pointers set to null.
The : syntax for constructors is called initialization lists. It's used here for initializing member fields in a simple, direct manner. Should be easy to google with the proper terminology.

C++ How do you set an array of pointers to null in an initialiser list like way?

I am aware you cannot use an initialiser list for an array. However I have heard of ways that you can set an array of pointers to NULL in a way that is similar to an initialiser list.
I am not certain how this is done. I have heard that a pointer is set to NULL by default, though I do not know if this is guaranteed/ in the C++ standard. I am also not sure if initialising through the new operator compared to normal allocation can make a difference too.
Edit: I mean to do this in a header file/constructor initialisation list. I do not want to put it in the constructor, and I do not want to use a Vector.
In order to set an array of pointers to nulls in constructor initializer list, you can use the () initializer
struct S {
int *a[100];
S() : a() {
// `a` contains null pointers
}
};
Unfortunately, in the current version of the language the () initializer is the only initializer that you can use with an array member in the constructor initializer list. But apparently this is what you need in your case.
The () has the same effect on arrays allocated with new[]
int **a = new int*[100]();
// `a[i]` contains null pointers
In other contexts you can use the {} aggregate initializer to achieve the same effect
int *a[100] = {};
// `a` contains null pointers
Note that there's absolutely no need to squeeze a 0 or a NULL between the {}. The empty pair of {} will do just fine.
Normally an array will not be initialised by default, but if you initialise one or more elements explicitly then any remaining elements will be automatically initialised to 0. Since 0 and NULL are equivalent you can therefore initialise an array of pointers to NULL like this:
float * foo[42] = { NULL }; // init array of pointers to NULL
You can switch from array to std::vector and use
std::vector<T*> v(SIZE);
The values will be initialized by NULLs automatically. This is the preferred C++ way.
Update: Since C++11, there is one more way: using
std::array<T*, SIZE> array = {};
This behaves more like a corrected version of C-style array (in particular, avoids dynamic allocations), carries its size around and doesn't decay to a pointer. The size, however, needs to be known at compile time.
I am not certain how this is done. I have heard that a pointer is set to NULL by default, though I do not know if this is guaranteed/ in the C++ standard.
It is not guaranteed by the C++ standard. Built in types ( like pointers ) are filled with garbage unless set otherwise.
I am also not sure if initialising through the new operator compared to normal allocation can make a difference too.
What do you mean by "normal allocation" ? If you're talking about an automatic variable, then you can do this:
MyType * pointers[2] = {}
and the pointers should be initialized to NULL.
void* p[10] = { 0 };
If you have a member array then there is no way to initialize, unless it's a static member. If the array isn't a static member then you'll have to fill it inside the constructor's body.
That said, chances are you're really better off using a std::vector. Other than for technical reasons such as unavailability of a standard STL for your platform, or the slightly lesser performance a std::vector is better than an array by any and all criteria. If performance is the issue then make sure you profiled and know by numbers that it is an issue.

Can I specify default value?

Why is it that for user defined types when creating an array of objects every element of this array is initialized with the default constructor, but when I create an array of a built-in type that isn't the case?
And second question: Is it possible to specify default value to be used while initializing elements in the array? Something like this (not valid):
char* p = new char[size]('\0');
And another question in this topic while I'm with arrays. I suppose that when creating an array of user defined type, every element of this array will be initialized with default value. Why is this?
If arrays for built in types do not initialize their elements with their defaults, why do they do it for User Defined Types?
Is there a way to avoid/circumvent this default construction somehow? It seems like bit of a waste if I for example have created an array with size 10000, which forces 10000 default constructor calls, initializing data which I will (later on) overwrite anyway.
I think that behaviour should be consistent, so either every type of array should be initialized or none. And I think that the behaviour for built-in arrays is more appropriate.
That's how built-in types work in C++. In order to initialize them you have to supply an explicit initializer. If you don't, then the object will remain uninitialized. This behavior is in no way specific to arrays. Standalone objects behave in exactly the same way.
One problem here is that when you are creating an array using new[], you options for supplying an initializer (in the current version of the language) are very limited. In fact, the only initializer you can supply is the empty ()
char* p = new char[size]();
// The array is filled with zeroes
In case of char type (or any other scalar type), the () initializer will result in zero-initialization, which is incidentally what you tried to do.
Of course, if your desired default value in not zero, you are out of luck, meaning that you have to explicitly assign the default values to the elements of the new[]-ed array afterwards.
As for disabling the default constructor call for arrays of types with user-defined default constructor... well, there's no way to achieve that with ordinary new[]. However, you can do it by implementing your own array construction process (which is what std::vector does, for one example). You first allocate raw memory for the entire array, and then manually construct the elements one-by-one in any way you see fit. Standard library provides a number of primitive intended to be used specifically for that purpose. That includes std::allocator and functions like uninitialized_copy, uninitialized_fill and so on.
Something like this (not valid):
As far as I know that is perfectly valid.
Well not completely, but you can get a zero intialized character array:
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[])
{
//The extra parenthesis on the end call the "default constructor"
//of char, which initailizes it with zero.
char * myCharacters = new char[100]();
for(size_t idx = 0; idx != 100; idx++) {
if (!myCharacters[idx])
continue;
std::cout << "Error at " << idx << std::endl;
std::system("pause");
}
delete [] myCharacters;
return 0;
}
This program produces no output.
And another question in this topic while I'm with arrays. I suppose that when creating an array of user defined type and knowing the fact that every elem. of this array will be initialized with default value firstly why?
Because there's no good syntactic way to specialize each element allocated with new. You can avoid this problem by using a vector instead, and calling reserve() in advance. The vector will allocate the memory but the constructors will not be called until you push_back into the vector. You should be using vectors instead of user managed arrays anyway because new'd memory handling is almost always not exception safe.
I think that behaviour should be consistent, so either every type of array should be initialized or none. And I think that the behaviour for built-in arrays is more appropriate.
Well if you can think of a good syntax for this you can write up a proposal for the standard -- not sure how far you'll get with that.
Why is it that for user defined types when creating an array of objects every element of this array is initialized with the default constructor, but when I create an array of a built-in type that isn't the case? and
And another question in this topic while I'm with arrays. I suppose that when creating an array of user defined type, every element of this array will be initialized with default value. Why is this? and
If arrays for built in types do not initialize their elements with their defaults, why do they do it for User Defined Types?
Because a user defined type is never ever valid until its constructor is called. Built in types are always valid even if a constructor has not been called.
And second question: Is it possible to specify default value to be used while initializing elements in the array? Something like this (not valid):
Answered this above.
Is there a way to avoid/circumvent this default construction somehow? It seems like bit of a waste if I for example have created an array with size 10000, which forces 10000 default constructor calls, initializing data which I will (later on) overwrite anyway.
Yes, you can use a vector as I described above.
Currently (unless you're using the new C++0x), C++ will call the constructor that takes no arguments e.g. myClass::myClass(). If you want to initialise it to something, implement a constructor like this that initialises your variables. e.g.
class myChar {
public:
myChar();
char myCharVal;
};
myChar::myChar(): myCharVal('\0') {
}
The C++ philosophy is - don't pay for something you don't need.
And I think the behviour is pretty unified. If your UDT didn't have a default constructor, nothing would be run anyway and the behaviour would be the same as for built-in types (which don't have a default constructor).
Why is it that for user defined types when creating an array of objects every element of this array is initialized with the default constructor, but when I create an array of a built-in type that isn't the case?
But if the default constructor of an object does nothing then it is still not initialiized.
class X
{
public:
char y;
}
X* data = new X[size]; // defaut constructor called. But y is still undefined.
And second question: Is it possible to specify default value to be used while initializing elements in the array? > Something like this (not valid):
Yes:
char data1[size] = { 0 };
std::vector<char> data2(size,0);
char* data3 = new char[size];
memset(data3,0,size);
Is there a way to avoid/circumvent this default construction somehow? It seems like bit of a waste if I for example have created an array with size 10000, which forces 10000 default constructor calls, initializing data which I will (later on) overwrite anyway.
Yes. Use a std::vector.
You can reserve the space for all the elements you need without calling the constructor.
std::vector<char> data4;
data4.reserve(size);

Does a type require a default constructor in order to declare an array of it?

I noticed that when you declare an array, the default constructor must be needed. Is that right?
Is there any exception?
For example,
struct Foo{
Foo(int i ) {}
};
int main () {
Foo f[5];
return 0;
}
The code above does not compile.
Other answers are all right but, for completeness: You could also use the array initialization syntax:
Foo f[5] = {1,2,3,4,5};
This works if Foo's ctor is not explicit. If it was, you'd have to be.... explicit:
Foo f[5] = {Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)};
Note1: There is a difference between the two cases that may not be obvious and is thus worth noting: In the first, the array elements are directly constructed from the ints in the initialization list, by invoking the Foo(int) ctor. In the second, the initialization list is made of Foos constructed with the explicit Foo(int) ctor, and the array elements are copy constructed from the elements in the initialization list. A copy ctor for Foo is thus required in the latter case.
[1] Thanks to MSalters for the comment.
The issue has nothing to do with arrays at all.
When you default-initialize an object of class type, the default constructor is required. If your class has no default constructor, then you have no other choice but to supply an explicit initializer when creating objects of that class. That's all.
By declaring a non-default constructor in your class Foo, you disabled the implicit generation of the default one, so now you'll have to supply an initializer every time you create a Foo object, regardless of whether it is an array element or not.
This declaration
Foo f; // ERROR
is not an array, but it will not compile for the very same reason. In order for it to compile you'll have to supply an explicit initializer
Foo f(3); // OK
The same thing happens with array, except that in that case you have to supply an initializer for each element using the aggregate initializer syntax
Foo f[5] = { 1, 2, 3, 4, 5 };
Of course, if you end up in a context where aggregate initializer syntax is not allowed (in the current version of C++ standard), like constructor initializer list or new-expression, then you are indeed screwed. In such contexts the only way out is to provide the default constructor in array element type (as long as you stick with built-in arrays).
That code doesn't compile because the compiler doesn't know what you want to pass to the constructor of each element, of course. There are basically two ways to go about it:
Make the array a vector, and pass it the desired size plus a single element -- this gives each element the same argument.
Make the array an array of pointers, and construct each element using a for loop and the new operator. The drawback of course, is that you have to free each element later as well.
See the C++ FAQ Lite, section 10.5
When you create an array, the default constructor gets called for each element in the array.
"If your class doesn't have a default constructor, you'll get a compile-time error when you attempt to create an array "
Prefer to use std::vector instead of the built-in arrays, though.
There is no exception. In what could be seen as exception, there is a compiler declared default constructor.
Note that a default constructor is not required if you use std::vector instead of an array - you can specify the constructor to be used:
std::vector <Foo> f; // OK
std::vector <Foo> f( 5, Foo(0) ); // also OK
No it doesn't.
An array, in C/C++ is a block of memory. Creating an array is reserving that block. Creating the objects is "1. Allocating the space 2. Running the constructors on each block" So, if you have an object without a constructor, you can still make an array of it (since that object has a size and since memory understands "size").
In short, it doesn't make any difference whatsoever. You will be running the constructors as you create the objects to fill the array with, or as said previously, when you assign it to something (which in turn, allocates space, runs the constructor).
Yes, you need the default constructor here because Foo f[5]; actually creates 5 Foos. You can work around this by making it a Foo* f[5] and then creating the 5 Foos with new.
For example:
Foo* f[5];
for(int i = 0; i < 5; ++i) {
f[i] = new Foo(i);
}
// later on...
f[0]->whatever();
Warning: slightly off-topic.
If you have a class without default constructor, you absolutely need to have an array, and you don't want to incur into the overhead of dynamic memory allocation, you can use an array of boost::optionals:
boost::optional<Foo> foos[4]; // Stack storage allocated but no objects
// constructed (roughly equivalent to what
// you get with vector<T>::reserve)
if(foos[2]) // Check if the third element has been constructed
{
foos[2]->bar(); // Access members of Foo with arrow
}
foos[1] = Foo(1, "a"); // Constructs the second element
foos[1].reset(); // Destroy second element (storage remains there though)
Unfortunately, you won't be able to pass this to a function expecting a true Foo[].