Compare four different codes with pointer.

I

Immortal Nephi

Please recommend me which ordinary function pointer, member function
pointer, or functionoids should I use? C++ Compiler should be able to
tune best optimization as possible when frequent functions are used in
the cache.
I can’t point which ordinary function pointer or member function
pointer should be fast enough. My explanation may be too long with
four different codes. Please bear patience. Thank you.
I write C style code example below. I do not place global variables
on the file scope. I place them in the struct.
Each function shares three variables in a struct. One parameter is a
pointer to struct because I want each function to modify variables in
a struct directly through a pointer. I can create one or more structs
because each struct has its own separated data copy.
The struct does not have constructor function. I must define struct
inside main() function before I must initialize three variables to one
or two manually.
I will show you C++ style code momentarily. Here is C style code
below.

struct Data
{
int a;
int b;
int c;
};

void Funct1( Data *data )
{
data->a += 0x1;
data->b -= 0x1;
data->c *= 0x2;
}

void Funct2( Data *data )
{
data->a += 0x10;
data->b -= 0x10;
data->c *= 0x20;
}

void Funct3( Data *data )
{
data->a += 0x100;
data->b -= 0x100;
data->c *= 0x200;
}

void Funct4( Data *data )
{
data->a += 0x1000;
data->b -= 0x1000;
data->c *= 0x2000;
}

void ( *Funct_Ptr[4] )( Data *data ) =
{
Funct1, Funct2, Funct3, Funct4
};

int main()
{
Data data1; /* First Struct */
data1.a = 1;
data1.b = 1;
data1.c = 1;

Data data2; /* Second Struct */
data2.a = 2;
data2.b = 2;
data2.c = 2;

int select_func = 0;

for( int loop = 0; loop < 12; loop++ )
{
Funct_Ptr[ select_func++ ]( &data1 );
select_func &= 3;
}

for( int loop = 0; loop < 12; loop++ )
{
Funct_Ptr[ select_func++ ]( &data2 );
select_func &= 3;
}

return 0;
}


The C style code does not look good because it does not have
wrapper. I moved funct1, funct2, funct3, funct4, and function pointer
into class Data. Each function does not have parameter so I don’t
need to use pointer to struct Data anymore.
Class Data does have constructor with initialization list. It looks
very neat. Here is my C++ style code below to compare against C style
code. You saw that class data1 and class data2 have their own copy of
data members.
I tell you functionoids momentarily.


class Data
{
public:
Data( int x, int y, int z ) : a( x ), b( y ), c( z ) {}
~Data() {}

void Funct1()
{
a += 0x1;
b -= 0x1;
c *= 0x2;
}

void Funct2()
{
a += 0x10;
b -= 0x10;
c *= 0x20;
}

void Funct3()
{
a += 0x100;
b -= 0x100;
c *= 0x200;
}

void Funct4()
{
a += 0x1000;
b -= 0x1000;
c *= 0x2000;
}

void ( *Funct_Ptr[4] )();

private:
int a;
int b;
int c;
};


void ( Data::*Funct_Ptr[4] )() =
{
&Data::Funct1, &Data::Funct2, &Data::Funct3, &Data::Funct4
};

int main()
{
Data data1( 1, 1, 1 ); /* First Struct */

Data data2( 2, 2, 2 ); /* First Struct */

int select_func = 0;

for( int loop = 0; loop < 12; loop++ )
{
( data1.*Funct_Ptr[ select_func++ ] )();
select_func &= 3;
}

for( int loop = 0; loop < 12; loop++ )
{
( data2.*Funct_Ptr[ select_func++ ] )();
select_func &= 3;
}

return 0;
}

They said member function pointer is slow than ordinary function
pointer. Yes, I agree. Member function pointer is rarely used. I
converted member function pointer into four derived classes. Each
derived class is class funct1, class funct2, class funct3, and class
funct4.
Here is my functionoids code below. I will tell you momentarily why
I am not satisfied.

class Data
{
public:
Data( int x, int y, int z ) : a( x ), b( y ), c( z ) {}
~Data() {}

virtual void Funct_Ptr() = 0;

protected:
int a;
int b;
int c;
};

class Funct1 : public Data
{
public:
Funct1( int x, int y, int z ) : Data( x, y, z ) {}
~Funct1() {}

virtual void Funct_Ptr()
{
a += 0x1;
b -= 0x1;
c *= 0x2;
}
};

class Funct2 : public Data
{
public:
Funct2( int x, int y, int z ) : Data( x, y, z ) {}
~Funct2() {}

virtual void Funct_Ptr()
{
a += 0x10;
b -= 0x10;
c *= 0x20;
}
};

class Funct3 : public Data
{
public:
Funct3( int x, int y, int z ) : Data( x, y, z ) {}
~Funct3() {}

virtual void Funct_Ptr()
{
a += 0x100;
b -= 0x100;
c *= 0x200;
}
};

class Funct4 : public Data
{
public:
Funct4( int x, int y, int z ) : Data( x, y, z ) {}
~Funct4() {}

virtual void Funct_Ptr()
{
a += 0x1000;
b -= 0x1000;
c *= 0x2000;
}
};

int main()
{
Funct1 data1_a( 1, 1, 1 );
Funct2 data1_b( 2, 2, 2 );
Funct3 data1_c( 3, 3, 3 );
Funct4 data1_d( 4, 4, 4 );

Funct1 data2_a( 11, 11, 11 );
Funct2 data2_b( 22, 22, 22 );
Funct3 data2_c( 33, 33, 33 );
Funct4 data2_d( 44, 44, 44 );

Data *data1_ptr[4] = { &data1_a, &data1_b, &data1_c, &data1_d }; /*
First Struct */
Data *data2_ptr[4] = { &data2_a, &data2_b, &data2_c, &data2_d }; /*
Second Struct */

int select_func = 0;

for( int loop = 0; loop < 12; loop++ )
{
data1_ptr[ select_func++ ]->Funct_Ptr();
select_func &= 3;
}

for( int loop = 0; loop < 12; loop++ )
{
data2_ptr[ select_func++ ]->Funct_Ptr();
select_func &= 3;
}

return 0;
}

Do you notice that each derived class has its own copy of data
members? How can member function pointer share class Data’s data
members – a, b, and c? They can, but functionoids can’t.
You are going to say – yes, static on data members is the option.
What if I say you can’t do it? I tell you the reason. data1 and
data2 have their own copy of data members. Member function pointer
can modify data1’s data members **AND** data2’s data members. Not a
problem.
You declare static data members before data1_ptr of base class’ data
members and data2_ptr of base class’ data members are shared. How
disappointment I am? What option do I have? Should I stick C style
code? Or…do I try to work and accommodate functionoids?
I may not want to move data members from class Data to another class
StandAlone. Also, I may not want to assign pointer to StandAlone
class in the parameter of class Data’s constructor. Unfortunately,
each derived class must access private a, b, c through getters &
setters fuctions so I use public instead.
Here is my functionoids with class StandAlone code below. You can
compare both of different functionoids codes above and below. Please
let me know which is best. Should I stick with member function
pointer or functionoids. I am not very sure.
I do know that functionoids have to build separate vtables which
require more memory space than member function pointer.
Please advise…

class StandAlone
{
public:
StandAlone( int x, int y, int z ) : a( x ), b( y ), c( z ) {}
~StandAlone() {}

int a;
int b;
int c;
};

class Data
{
public:
Data( StandAlone *_StandAlone ) : pStandAlone( _StandAlone ) {}
~Data() {}

virtual void Funct_Ptr() = 0;

StandAlone *pStandAlone;
};


class Funct1 : public Data
{
public:
Funct1( StandAlone * _StandAlone ) : Data( _StandAlone ) {}
~Funct1() {}

virtual void Funct_Ptr()
{
pStandAlone->a += 0x1;
pStandAlone->b -= 0x1;
pStandAlone->c *= 0x2;
}
};

class Funct2 : public Data
{
public:
Funct2( StandAlone * _StandAlone ) : Data( _StandAlone ) {}
~Funct2() {}

virtual void Funct_Ptr()
{
pStandAlone->a += 0x10;
pStandAlone->b -= 0x10;
pStandAlone->c *= 0x20;
}
};

class Funct3 : public Data
{
public:
Funct3( StandAlone * _StandAlone ) : Data( _StandAlone ) {}
~Funct3() {}

virtual void Funct_Ptr()
{
pStandAlone->a += 0x100;
pStandAlone->b -= 0x100;
pStandAlone->c *= 0x200;
}
};

class Funct4 : public Data
{
public:
Funct4( StandAlone * _StandAlone ) : Data( _StandAlone ) {}
~Funct4() {}

virtual void Funct_Ptr()
{
pStandAlone->a += 0x1000;
pStandAlone->b -= 0x1000;
pStandAlone->c *= 0x2000;
}
};

int main()
{
StandAlone data1( 1, 1, 1 );
StandAlone data2( 2, 2, 2 );

Funct1 data1_a( &data1 );
Funct2 data1_b( &data1 );
Funct3 data1_c( &data1 );
Funct4 data1_d( &data1 );

Funct1 data2_a( &data2 );
Funct2 data2_b( &data2 );
Funct3 data2_c( &data2 );
Funct4 data2_d( &data2 );

Data *data1_ptr[4] = { &data1_a, &data1_b, &data1_c, &data1_d }; /*
First Struct */
Data *data2_ptr[4] = { &data2_a, &data2_b, &data2_c, &data2_d }; /*
Second Struct */

int select_func = 0;

for( int loop = 0; loop < 12; loop++ )
{
data1_ptr[ select_func++ ]->Funct_Ptr();
select_func &= 3;
}

for( int loop = 0; loop < 12; loop++ )
{
data2_ptr[ select_func++ ]->Funct_Ptr();
select_func &= 3;
}

return 0;
}

End
 
A

Alexander Bartolich

Immortal said:
[...]
class Data
{
public:
[...]
void ( *Funct_Ptr[4] )();

This is strange. Why is the array of function pointers an instance
variable? The equivalent of your C-style solution would be

static const void ( *Funct_Ptr[4] )();
private:
int a;
int b;
int c;
};


void ( Data::*Funct_Ptr[4] )() =
{
&Data::Funct1, &Data::Funct2, &Data::Funct3, &Data::Funct4
};

Since every instance is initialized with the same set of pointers
you definitely want a class member.
They said member function pointer is slow than ordinary function
pointer.

That is because you are using instance members instead of class
members.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top