Dereferencing object array pointer in C++ - c++

I have this small question about dereferencing arrays. I have a method in class like this
T* foo()
{
// create specific array of objects in here
return (array)
}
foo2()
{
myNewArray = *foo();
// exactly the same algorithm as in foo to create checkArray
cout << sizeof(myNewArray) << sizeof(checkArray) << endl;
}
I get two different results, but I expect them to be the same?
Ok, so the additional information about the code:
vec4* getGridAttr()
{
float xval = -0.5;
float yval = -0.75;
float xval2 = -0.5;
float yval2 = -0.75;
vec4 pointsGrid[100];
for (int i=0;i<42;i++)
{
//Draw horizontal lines
if (i % 2 == 0) pointsGrid[i] = vec4(xval, yval, 0.0,1);
else if (i % 2 != 0) {
pointsGrid[i] = vec4((xval+0.75), yval, 0.0,1);
yval += 0.075;
}
}
for (int j=42;j<64;j++)
{
//Draw horizontal lines
if (j % 2 != 0)
{
pointsGrid[j] = vec4(xval2, yval2, 0.0,1);
xval2 += 0.075;
}
else if (j % 2 == 0) {
pointsGrid[j] = vec4(xval2, -yval2, 0.0,1);
}
}
return (pointsGrid);
}
and in my other method, i have this:
void display( void )
{
vec4 points1[100];
//code here populates points1 exactly the same as in getGridAttributes,
cout << "points1 : " << sizeof(points1) << " " << " pointsFromGridAttr : " << sizeof(*getGridAttr()) << endl;
}
The output is points1 : 1600 pointsFromGridAttr 16

Without seeing more code I can't be sure of this, but if you have something like this:
T* arr1 = makeArray();
T arr2[n];
Then arr1 and arr2 would have different sizes. Specifically, arr1 is a pointer, so its size is the size of a pointer, while arr2 is an array, and its size will be the size of a T object times the number of objects in the array.
Although arrays and pointers in C++ can be interchanged in some contexts, they really are different types. T* and T [n] are different types with different sizes. Once an array decays to a pointer, it loses its size information.
Hope this helps!

I guess you would like to compare the length of the arrays. The length of a C array should be calculated as sizeof(array_variable) / sizeof(type_of_array_elements) or sizeof(array_variable) / sizeof(one_element), not just as sizeof(array_variable). For details see this SO question.
Try this:
cout << sizeof(myNewArray) / sizeof(myNewArray[0]) << ", " << sizeof(checkArray) / sizeof(checkArray[0]) << endl;

Related

Array values reset problem with dynamic allocation

Trying to create a little program using class, dynamic allocation,...
This is the "problematic" code:
void Social::calc_pop(double years) const {
double var = births - deaths;
double* pop = new double;
pop[0] = pop_0;
for (int i = 0; i < years; i++)
{
pop[i+1] = pop[i] + var;
std::cout << "La popolazione all'anno " << i+1 << " è pari a " << pop[i+1] << std::endl;
}
delete pop;
}
The output is (with years = 10, pop_0 = 300, births = 10, deaths = 9):
pop[1] = 301
pop[2] = 302
pop[3] = 303
pop[4] = 304
pop[5] = 1
pop[6] = 1
pop[7] = 1
pop[8] = 2
pop[9] = 3
pop[10] = 4
What's wrong with my code?
This code:
double* pop = new double;
allocates a single double, but then you are treating pop like an array, which invokes undefined behavior when you index into it at any position other than 0.
Instead, you need to allocate an array:
double* pop = new double[years + 1];
Note that you need to make years an int, or cast it to an int inside the new expression.
which is later deleted like this:
delete [] pop;
However, please don't write this code (unless you're just practicing how dynamic allocation works). You can save yourself a lot of trouble by just making pop a vector:
std::vector<double> pop(years + 1);
You're only allocating a single double, which you treat as an array, and that has undefined behaviour if the index is greater than zero.
You also can't allocate an array of years elements, because years is not an integer – what would an array of 3.125 doubles look like?
You don't need any kind of collection for this calculation, only the last known value.
void Social::calc_pop(int years) const {
double var = births - deaths;
double pop = pop_0;
for (int i = 0; i < years; i++)
{
pop = pop + var;
std::cout << "La popolazione all'anno " << i+1 << " è pari a " << pop << std::endl;
}
}

Using the original values of a vector after manipulation

I am trying to convert vector values that are received form a file into two different formats. After converting into first format and printing the vector out, I want to use the original "read in" values to convert them into the second format.
At the moment, it seems that the second conversion is happening on the already converted values. However, I don't understand why it doesn't convert back to the original value then? And ultimately, how can I use the original values of the vector for the second conversion so the
else {
GetType();
GetXArg();
GetYArg();
}
works for the second time?
Here is the code snippet:
void Force::convToP() //converts to polar
{
if (forceType == 'c')
{
SetType('p');
SetXArg(sqrt(xArg * xArg + yArg * yArg));
SetYArg(atan(yArg / xArg));
}
else {
GetType(); //just return type, xArg and yArg in their original form
GetXArg();
GetYArg();
}
}
void Force::convToC() //converts to cartesian
{
if (forceType == 'p') {
SetType('c');
SetXArg(xArg * cos(yArg));
SetYArg(xArg * sin(yArg));
}
else {
GetType();
GetXArg();
GetYArg();
}
}
and the main function:
while (file >> type >> x >> y) {
Force f(type, x, y);
force.push_back(f);
}
for (int i = 0; i < force.size(); ++i) {
force[i].printforce();
}
cout << "Forces in Polar form: " << endl;
for (int i = 0; i < force.size(); ++i)
{
force[i].convToP();
force[i].printforce();
}
cout << "Forces in Cartesian form: " << endl;
for (int i = 0; i < force.size(); ++i) {
force[i].convToC();
force[i].printforce();
}
finally, the output at the moment is:
p 10 0.5
c 12 14
p 25 1
p 100 0.8
c 50 50
p 20 3.14
c -100 25
p 12 1.14
Forces in Polar form: <-first conversion. All works fine
p 10 0.5
p 18.4391 0.649399
p 25 1
p 100 0.8
p 70.7107 0.61548
p 20 3.14
p 103.078 0.237941
p 12 1.14
Forces in Cartesian form:
c 8.77583 4.20736 <-works fine
c 14.6858 8.8806 <-why doesn't convert back to c 12 14/ how to use the original values of vector
c 13.5076 11.3662
c 69.6707 49.9787
c 57.735 33.3333
c -20 -0.0318509
c 100.173 23.6111
c 5.01113 4.55328
Press any key to continue . . .
Very new to this, been baffled for some time, so would really appreciate any help and advice.
You are modifying xArg and then using the modified value to convert yArg. You need to do both conversions before either modification.
void Force::convToP() //converts to polar
{
if (forceType == 'c')
{
forceType = 'p';
decltype(xArg) newX = sqrt(xArg * xArg + yArg * yArg);
decltype(yArg) newY = atan(yArg / xArg);
xArg = newX;
yArg = newY
}
// no else needed
}
void Force::convToC() //converts to cartesian
{
if (forceType == 'p') {
forceType = 'c';
decltype(xArg) newX = xArg * cos(yArg);
decltype(yArg) newY = xArg * sin(yArg);
xArg = newX;
yArg = newY
}
// no else needed
}
You can verify the correct values with std::complex
#include <complex>
#include <vector>
#include <iostream>
int main() {
std::vector<std::complex<double>> nums
{
std::polar<double>(10, 0.5),
std::complex<double>(12, 14),
std::polar<double>(25, 1),
std::polar<double>(100, 0.8),
std::complex<double>(50, 50),
std::polar<double>(20, 3.14),
std::complex<double>(-100, 25),
std::polar<double>(12, 1.14)
};
for (auto num : nums)
{
std::cout << num << " (" << std::abs(num) << ", " << std::arg(num) << ")\n";
}
}
(8.77583,4.79426) (10, 0.5)
(12,14) (18.4391, 0.86217)
(13.5076,21.0368) (25, 1)
(69.6707,71.7356) (100, 0.8)
(50,50) (70.7107, 0.785398)
(-20,0.0318531) (20, 3.14)
(-100,25) (103.078, 2.89661)
(5.01113,10.9036) (12, 1.14)
It's often helpful to break sub-operations down into small single-concern functions.
The compiler will optimise away all the redundant copies, loads and stores:
#include <cmath>
#include <tuple>
auto computed(double xArg, double yArg)
{
return
std::make_tuple(
std::sqrt(xArg * xArg + yArg * yArg),
std::atan(yArg / xArg));
}
void modify(double& xArg, double& yArg)
{
std::tie(xArg, yArg) = computed(xArg, yArg);
}
Without knowing exactly what GetXArg() etc. do, it appears that you are modifying your original forces when you call force[i].convToP();. So after this loop all the forces in your array are converted to polar. If all you want to do is print the polar and cartesian representations without changing the originals, you should generate copies of the forces:
cout << "Forces in Polar form: " << endl;
for (int i = 0; i < force.size(); ++i)
{
Force tmpForce = force[i];
tmpForce.convToP();
tmpForce.printforce();
}
etc.
Edit: Looks like #Aconcagua beat me to it.
Your conversion function obviously changes the object it operates on. Then you need to be aware that the index operator ([]) returns a reference to the object in the vector. If you do not want to modify the original object, you'll have to make a copy of:
for (int i = 0; i < force.size(); ++i)
{
auto copy = force[i]
copy.convToP();
copy.printforce();
}
Now, you can operate on the unchanged values in the second run. Assuming you don't need the original values afterwards any more, you can just leave the second loop as is, otherwise, make copies again...
All a little easier with range based for loop:
for(auto c : force)
{
c.convToP();
c.printforce();
}
for(auto& c : force)
// ^ if you don't need original values any more, can use reference now
{
c.convToC();
c.printforce();
}

C++ vectors of values returning a matrix

I have 4 integer variables - x,y,z,t which could get values from an interval of integer values [a,b] ) ( the interval is a,a+1,a+2,...,b ).
I want to set a vector of distinct {x,y,z,t} values with the following rule:
2 quartets (x and y) are not equal if there exists at least one quartet value for which : x.i != y.i (i is one of the {x,y,z,t} value positions).
My current solution is extremely time consuming:
struct gim
{
int xx;
int yy;
int zz;
int tt;
}
vector<gim> v;
x=a;y=a;z=a;t=a;
nr_quartet=0;
gim g;
while(x<=b)
{
while(y<=b)
{
while(z<=b)
{
while(t<=b)
{
if(at least one of x,y,z,t is different)
{
nr_quartet++;
g.xx=x;
g.yy=y;
g.zz=z;
g.tt=t;
v.push_back(g);
cout << x << " " << y << " " << z << " " << t << "\n";
}
t++;
}
z++;
}
y++;
}
x++;
}
You can try something like this:
int actual_t = t;
int actual_z = z;
int actual_y = y;
int actual_x = x;
while(t<=b && z <=b && y<=b && x<=b)
{
if(at least one of x,y,z,t is different)
{
nr_quartet++;
v.emplace_back(x, y, z, t);
//cout << x << " " << y << " " << z << " " << t << "\n";
}
// For t
if(t==b)
{
t = 0;
}
else
{
t++;
}
actual_t = t;
// For z
if(z==b)
{
z = 0;
}
else if(/* incrementation condition for z */)
{
z++;
}
actual_z = z;
/* the same for y and x */
}
If you only need the number of elements of the set {(x,y,z,t) | ¬(x = y = z = t)}, then compute (b-a)**4 - (b-a); i.e. no need to iterate through all of them.
If you really need to fill a vector with all the combinations, well, you will have to iterate to add them all. The longest part will be memory allocations inside the std::vector, so pre-reserve or pre-resize with the number of elements since you can know it in advance.
As far as I've done is something which is consuming much time
What do you mean it is consuming a lot of time? What is your [a, b] range?

Making Terrain Strip in c++ & returning 2d array

I'm screwing around with opengl in c++, this is my first time really writing anything in c++, so I'm having troubles with pointers and arrays. I'd like to make a function that makes a strip of terrain (represented by an array of vertices, each vertex being an array of 3 floats) and returns it. This 2d array (unknown sized array of 3 sized arrays) can then be rendered with gl triangles. I'm not having any trouble with rendering it, but when my code runs currently, when I log the values of the vertices in the array local to the function, everything is fine, but in the main source, the values aren't logged correctly.
tl;dr:
How can I generate an array of arrays in a c++ function.
Here's my function right now:
float** makeTerrainStrip(float tile, unsigned int tiles)
{
float** strip = new float*[(tiles + 1) * 2];
for (unsigned int i = 0; i < tiles; i++) {
float x = i * tile;
float y = 0;
float z1 = 0;
float z2 = tile;
float v1[3] = {x, y, z1};
float v2[3] = {x, y, z2};
strip[i * 2] = v1;
strip[i * 2 + 1] = v2;
}
std::cout << strip[0][0] << std::endl;
std::cout << strip[0][1] << std::endl;
std::cout << strip[0][2] << std::endl;
return strip;
}
and it gets called from the main source here:
strip = makeTerrainStrip(1, 5); // strip is a global defined earlier
std::cout << strip[0][0] << std::endl;
std::cout << strip[0][1] << std::endl;
std::cout << strip[0][2] << std::endl;
Here's the output:
// in the function
4
0
0
// in the main source
4
1.26749e+029
7987.1

I'm trying to Normalise a vector but my code returns a fail?

Below is my code sample, trying to normalize my 3 point vector {5, 5, 5}
however it is printing "Normalise - Failed" when running, may someone explain why it isn't succeeding this to me so i may attempt to fix it?
#include <iostream>
#include "Geometry.h"
#include <math.h>
void Normalise()
{
TVector3 _krA;//vector / mag vector = answer x y z
{
_krA.m_fX = 5;
_krA.m_fY = 5;
_krA.m_fZ = 5;
}
TVector3 _rResultant;
{
_rResultant.m_fX = (_krA.m_fX * _krA.m_fX);
_rResultant.m_fY = (_krA.m_fY * _krA.m_fY);
_rResultant.m_fZ = (_krA.m_fZ * _krA.m_fZ);
}
float _fResultFinalMag = sqrt(_rResultant.m_fX + _rResultant.m_fY + _rResultant.m_fZ);
float _fresultXMag = (_krA.m_fX / _fResultFinalMag);
float _fresultYMag = (_krA.m_fY / _fResultFinalMag);
float _fresultZMag = (_krA.m_fZ / _fResultFinalMag);
float _fNormliseTestX = 0.577350;
float _fNormliseTestY = 0.577350;
float _fNormliseTestZ = 0.577350;
if (_fNormliseTestX == _fresultXMag && _fNormliseTestY == _fresultYMag && _fNormliseTestZ == _fresultZMag)
{
std::cout << "Normalise - Success" << std::endl;
}
else
{
std::cout << "Normalise - Failed" << std::endl;
std::cout << _fresultXMag << std::endl;
std::cout << _fresultYMag << std::endl;
std::cout << _fresultZMag << std::endl;
std::cout << _fResultFinalMag << std::endl;
}
}
The reason your code prints "Failed", is because you're comparing float values exactly using ==. Floating point data types don't generally store values exactly, but instead store them with a certain precision. Furthermore, they're subject to rounding errors, further compounded the more calculations you perform with the values.
Have a read through this C++ FAQ entry about "Why doesn’t my floating-point comparison work?" for a good explanation.
One option you have, is to compare using an epsilon :
float epsilon = 0.0001; // or whatever accuracy you require
if (fabs(_fNormliseTestX - _fresultXMag) < epsilon) {
// _fNormliseTestX and _fresultXMag are considered equal
}