When to use dynamic array or a vector??

I am writing a program that deals with statistical math and passes a lot of number back and forth between functions. There are a lot of arrays that are being handled and some of them need to be dynamic. My question is when should I use vectors and when should I be using dynamic arrays. Is there any advantage to one rather than the other ? I would prefer to use only one through out the whole code to make it easier but that may not be an option

My code is below it doesn't really have either implemented yet really I am only re-writing the code now to use these features....

Any suggestions or tips with my writing style would also be appreciated
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

#include<iostream>	
#include<cmath>
#include<string>
#include<fstream>

using namespace std;


//======================================================================
//				Functions 
//======================================================================


void mathmodel (double ji, double jm, double l1, double f22, double f42, 
		double* data[][3], double* values[][6], double* model[])
{

//this function does the w(theta) calculation for the model 

	int i,x ;
	double f2, f4;
	for ( i = 0 ; i<10 ; i++) {
	if (ji==*values[i][1] and jm==*values[i][0] and l1==*values[i][2]){
	
		f2 = *values [i][4];
		f4 = *values [i][5];	
	}
	}



	for (x=0; x<10 ; x++){
	*model[x] = 1 + f2*f22*1/2*(3* pow(cos(*data[x][0]),2) *-1 ) 
			+ f4*f42* 1/8*(35*pow(cos(*data[x][0]),4)
			- 30 *pow(cos(*data[x][0]),4) + 3);
	}


}

//======================================================================


double multer (double sig)
{
// this subroutine calcs the constant in front of the exponent summation
// that is constant during the test 

	double con ;
	double pi = 3.14159265359;
	con =  1/(sig * sqrt(2*pi));

return (con);
}

//======================================================================

double baysum (double h , double d, double sig)
{

// this sub does the summation portion of the Bayesian analysis 
	
	double sum ;
	sum =(-1*pow((h-d),2))/(2*pow(sig,2));

return (sum);
}
//======================================================================

double weight (double elevel, double atmass , double energy)
{

// this sub does the p(H|I) calcs for the weights before normalization
// all odd #'s are M's and evens are E's Order goes( E1,M1,E2,M2,ect..)

	float ph;
	if (elevel == 1) ph = 1.0e14*pow(atmass,2/3)*pow(energy,3);
	if (elevel == 2) ph = 7.3e7*pow(atmass,4/3)*pow(energy,5);
	if (elevel == 3) ph = 34*pow(atmass,2)*pow(energy,7);
	if (elevel == 4) ph = 1.e-5*pow(atmass,8/3)*pow(energy,7);
	if (elevel == 5) ph = 15.6e13*pow(energy,3);
	if (elevel == 6) ph = 3.5e7*pow(atmass,2/3)*pow(energy,5);
	if (elevel == 7) ph = 16*pow(atmass,4/3)*pow(energy,7);
	if (elevel == 8) ph = 4.5e-6*pow(atmass,2)*pow(energy,9);

return (ph);
}
//======================================================================


//======================================================================
//			MAIN PROG 
//======================================================================

int main () 
{
//FILLING DATA ARRAYS 
// ask user for dat file
 
	ifstream dat;
	do {
		cout << "Input filename where the raw data exist-->";
		char filename [50];
		cin.getline(filename,50);
		dat.open(a);
		if (!dat.is_open())
		cout << "File Does Not Exist!" << endl ;
	} while (!dat.is_open());

// read from file  and fill arrays 
// array reads angle, w(angle) errw(angle)

	double* data = new double [15][3]; 
	int x = 0; 
	double  a,b,c,d,e,f;

	while (	dat >> a >> b >> c){

		data[x][0] = a;
		data[x][1] = b;
		data[x][2] = c;

	//	cout << data[x][2] << endl;
		x++;
	}


// SECOND ARRAY FILLING 
// fill arrays for testing models 

	ifstream table;
	do {
		cout << "Input filename where the data table exist-->";
		char file [50];
		cin.getline(file,50);
		table.open(file);
			if (!table.is_open())
			cout << "File Does Not Exist!" << endl ;
	} while (!table.is_open());


	double values [10][6]; //array from 1967 table values are:
			      // jf , ji,l1,l2,f2,f4 
	x = 0 	;

	while (table >> a >> b >> c >> d >> e >> f){

		values [x][0] = a;
		values [x][1] = b;		
		values [x][2] = c;
		values [x][3] = d;
		values [x][4] = e;
		values [x][5] = f;


		x++;
	}		

	table.close();

// Ask user for the atomic mass & energy level 

	float atmass;
	cout << "Please enter the atomic mass number-->" ;
	cin >> atmass;



	float energy;
	cout << "Please enter the energy (Mev)-->" ;
	cin >> energy; 

	double elevel;
	double mlevel;


	double jm , ji , l1,l2 ,jf;
	jm = 9;
	jf = 7;
	l2 = 2 ;

	ji = 11;
	l1 = 2 ;

//	   Done Filling Arrays From File And Grabbing User Input 
//======================================================================


//  find the proper f2 and f4values from the table for the 
//	values that we already know ie jm jf and l2 
	
	double conf2, conf4;
	
	for ( x = 0 ; x<10 ; x++) {

	if (jm==values[x][1] and jf==values[x][0] and l2==values[x][3]){
	
		
		conf2 = values [x][4];
		conf4 = values [x][5];	
	}
	}


	double* pmodelw;
	pmodelw = new double[15];
	
	
	mathmodel( ji,  jm,  l1, conf2, conf4,&data, &values,&pmodelw);

	

return 0 ;
}
			

	
I am new to coding however maybe I can be a little helpful.

As you you know vectors work a lot like arrays. Vectors however open the door to some other STL built in functions like sorting and searching. This way you don't have to come up with the algs. yourself. Arrays are nice and trustee but if you wanted to do things like sort you would have to code it from scratch. Also vectors make it pretty easy to add new elements without needing to redefine the array by hand. You can also use iterators which make it easy to use find algorithms and to delete items in the vectors. Since you are calling vectors from a lib there is probably some performance draw back but really these have been optimized.


As you can see it is personal preference. If you just need a list without doing a lot to it I say go with arrays but if you need to perform lots of manipulation I would say go with vectors.



Hope this helped
> when should I use vectors and when should I be using dynamic arrays.

Almost always (always), prefer std::vector<>


> Is there any advantage to one rather than the other ?

See: http://www.stroustrup.com/bs_faq2.html#arrays
as ^ he said, always. vectors are awesome.
I would also like to add:

Some will argue that they are inefficient compared to arrays, but the performance difference is nominal. Vectors should be used for their member functions, such as pop_back() and push_back(), which allow the manipulation of it to be fairly simple and error free.
[W]hen should I use vectors and when should I be using dynamic arrays [?]

As has already been said, in C++ code you should always use std::vector over a dynanic array.

(I can't think of a reason to use a C-style array, unless there is no standard library available for some reason. But then I'd code my own array class rather than use a naked pointer.)

Any suggestions or tips with my writing style would also be appreciated

1. testing double values for equality can be problematic as the values aren't always accurate down to the last bit. You really need to test to see if they're close enough (within some 'epsilon'). See:

double - and how to use it
http://www.cplusplus.com/forum/articles/3827/

2. I don't get why you using a double* array? (line 24)

3. The variable names make it hard to see what's going on

4. main should be split up into multiple functions

5. pi could be declared at file scope, as a const, as it will be useful all the place. It's something that is ok to be global as it is, after all, a universal constant. Or even better, in a namespace?

By the way, the C header file math.h will probably already define it for you. You can either use it directly, or use its value to init a const double (which I do when I'm being more careful.) For my compiler, it's defined as

#define M_PI 3.14159265358979323846

(There is also M_PI_2 for pi/2, M_PI_4 for pi/4, and a then others.)

Note that while M_PI is not part of standard C, it is part of POSIX, so most compilers that target Linux and similar will provide it. The Visual C++ version of math.h does provide the definitions but you've got to #define _USE_MATH_DEFINES before including the header for them to be visible.

Edit: the GCC version of math.h has M_PI, but it is only available if __STRICT_ANSI__ has not been defined, as it is not part of ANSI C++.

6. preferred C++ style it to init variable in the statement as they're defined, e.g.

double sum =(-1*pow((h-d),2))/(2*pow(sig,2));

rather than

1
2
	double sum;
	sum =(-1*pow((h-d),2))/(2*pow(sig,2));


(This is a good habit to get into as when it's a variable of some type of class, rather than a built-in type like double, there are performance considerations. And while you could treat built-in types differently to class types, it is probably best to be consistent.)

And if a variable cannot be set to a useful value when it's declared, it should be initialized to either zero or some other appropriate value.

7. Similarly, in C++ you typically use (preferring ++i over i++ for ppossible performance issues/consistenvy reasons) and declare loop variable within the scope of the for-loop

for (int i = 0 ; i<10 ; ++i) {

not

1
2
3
int i;

for (int i = 0 ; i<10 ; i++) {


8. You need to remember to delete all you new... which is one of the reasons it's better to use std::vector

(For small amounts of memory, I have tended to use automatic arrays rather than vectors. These are created on the stack rather than the heap, like dynamic arrays. But C++11 now provides a std::array class which can be used for this purpose.)

9. If you need to do a lot of 2D array (or matrix) stuff, you might want to create a class.

10. This loop (from line 193 on)

1
2
3
4
5
6
7
8
9
10
11
	double conf2, conf4;
	
	for ( x = 0 ; x<10 ; x++) {

	if (jm==values[x][1] and jf==values[x][0] and l2==values[x][3]){
	
		
		conf2 = values [x][4];
		conf4 = values [x][5];	
	}
	}


should prob be something like


1
2
3
4
5
6
7
8
9
10
11
12
13
14
	double conf2 = 0.0;
	double conf4 = 0.0;
	found_match = false;

	for (int x = 0 ; x<10 && !found_match; ++x) {
		if (jm==values[x][1] && jf==values[x][0] && l2==values[x][3]) {
			conf2 = values [x][4];
			conf4 = values [x][5];
			found_match = true;	
		}
	}

	if(found_match) {
		//etc 


(I swapped the and for &&, as that's more usual)

Andy

Last edited on
Everything I have read and learnt up to now indicates that <vector> should be used when dealing with dynamic arrays. On the other hand, how to use them is another matter; at the moment, I can't say I am very knowledgeable about them.

One of the reasons I have resisted using vectors is because so much of my old code uses the standard way of passing a non-dynamic array into sub-routines.

For example,

void function1(double Matrix_A)
void function2(double Matrix_A)
void function3(double Matrix_A)
void function4(double Matrix_A)
etc.

To upgrade all this old code to use <vector>, all the sub-routine headers, definitions, and internal workings would have to be re-worked too.

For example,

void function1(vector<vector<double> > Matrix_A)
etc.

So far, I have found it easier to just put up with the extra hassle of manual house-keeping instead of re-writing all the routines.

But I think it is for my own good to learn how to use <vector>.

Last edited on
> To upgrade all this old code to use <vector>, all the sub-routine headers,
> definitions, and internal workings would have to be re-worked too.

Looking at the snippet that was posted, even without vectors, you may have a fair amount of re-writing to do to get the code into a compilable state.

For instance:
1
2
// double* data = new double [15][3] ;
double (*data)[3] = new double [15][3] ;


> much of my old code uses the standard way of passing a non-dynamic array into sub-routines.

You may not have to re-write all of it at one go. For instance:

1
2
3
4
5
6
7
void foo( const double* array, std::size_t n ) ; // old code

int main()
{
    std::vector<double> vec(100) ; // new code
    foo( &vec.front(), vec.size() ) ;
}


>> "You may not have to re-write all of it at one go. For instance: . . ."

That would be great.

Is that all there is to it? Just change a few sections of the main program but leave the sub-routines unchanged?

Thanks for the suggestion.
> Just change a few sections of the main program but leave the sub-routines unchanged?

No. Change them too; but at leisure, one by one, over a period of time.
Topic archived. No new replies allowed.