STL Vector question?

E

Elzbieta Burnett

I have:

struct point
{
double alpha, beta;
double Force;

point( double a, double b, double f ) : alpha(a), beta(b), Force(f)
{}
};

struct data
{
int dof;
int XYZ;
double X, Y, Z;
int node;
vector<point> pt;
};

map<int, data> AeroDOF;

I my initialization code I had:

AeroDOF[ dof[j] ].pt.push_back( point( alpha, beta,
Force[j] ) );

I thought that vector '[]' would create an instance of 'point' (like
map '[]'), call copy constructor and assign newly created entry to
point( alpha, beta, Force[j] ) in AeroDOF.pt.

Evidently this isn't true?

<Ella>
 
J

jski

I have:

struct point
{
  double alpha, beta;
  double Force;

  point( double a, double b, double f ) : alpha(a), beta(b), Force(f)
{}

};

struct data
{
  int dof;
  int XYZ;
  double X, Y, Z;
  int node;
  vector<point> pt;

};

map<int, data> AeroDOF;

I my initialization code I had:

        AeroDOF[ dof[j] ].pt.push_back( point( alpha, beta,
Force[j] ) );

I thought that vector '[]' would create an instance of 'point' (like
map '[]'), call copy constructor and assign newly created entry to
point( alpha, beta, Force[j] ) in AeroDOF.pt.

Evidently this isn't true?

<Ella>


Try:

struct data
{
int dof;
int XYZ;
double X, Y, Z;
int node;
vector<point *> pt;

};

AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );


Not sure what the answer to your question though.

---John
 
I

Ian Collins

Elzbieta said:
I have:

struct point
{
double alpha, beta;
double Force;

point( double a, double b, double f ) : alpha(a), beta(b), Force(f)
{}
};

struct data
{
int dof;
int XYZ;
double X, Y, Z;
int node;
vector<point> pt;
};

map<int, data> AeroDOF;

I my initialization code I had:

AeroDOF[ dof[j] ].pt.push_back( point( alpha, beta,
Force[j] ) );

I thought that vector '[]' would create an instance of 'point' (like
map '[]'), call copy constructor and assign newly created entry to
point( alpha, beta, Force[j] ) in AeroDOF.pt.

Evidently this isn't true?


The evidence has led you the the correct conclusion! The [] operator on
std::vector does not allocate storage.
 
E

Elzbieta Burnett

(e-mail address removed):








struct point
{
  double alpha, beta;
  double Force;
  point( double a, double b, double f ) : alpha(a), beta(b), Force(f)
{}
};
struct data
{
  int dof;
  int XYZ;
  double X, Y, Z;
  int node;
  vector<point> pt;
};
map<int, data> AeroDOF;
I my initialization code I had:
        AeroDOF[ dof[j] ].pt.push_back( point( alpha, beta,
Force[j] ) );


Your conclusion is right, but it does not follow from the above line. In
this line [] is used a lot, but the only case where the container type is
known it is a map (AeroDOF). All other variables where [] is applied to
are undefined/undeclared (dof, alpha, beta, Force) in your example and so
it is not clear if they are vectors, not to speak about how large they
are and if they are accessed out of bounds.


I thought that vector '[]' would create an instance of 'point' (like
map '[]'), call copy constructor and assign newly created entry to
point( alpha, beta, Force[j] ) in AeroDOF.pt.


On pt you are using push_back() which works more or less exactly as you
describe. Your problem is probably elsewhere.

Cheers
Paavo


If I use solution proposed by John:

vector<point *> pt)
AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );

this seems to work. Is there problem with this solution?

<Ella>
 
V

Victor Bazarov

(e-mail address removed):








struct point
{
double alpha, beta;
double Force;
point( double a, double b, double f ) : alpha(a), beta(b), Force(f)
{}
};
struct data
{
int dof;
int XYZ;
double X, Y, Z;
int node;
vector<point> pt;
};
map<int, data> AeroDOF;
I my initialization code I had:
AeroDOF[ dof[j] ].pt.push_back( point( alpha, beta,
Force[j] ) );


Your conclusion is right, but it does not follow from the above line. In
this line [] is used a lot, but the only case where the container type is
known it is a map (AeroDOF). All other variables where [] is applied to
are undefined/undeclared (dof, alpha, beta, Force) in your example and so
it is not clear if they are vectors, not to speak about how large they
are and if they are accessed out of bounds.


I thought that vector '[]' would create an instance of 'point' (like
map '[]'), call copy constructor and assign newly created entry to
point( alpha, beta, Force[j] ) in AeroDOF.pt.


On pt you are using push_back() which works more or less exactly as you
describe. Your problem is probably elsewhere.

Cheers
Paavo


If I use solution proposed by John:

vector<point *> pt)
AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );

this seems to work. Is there problem with this solution?


Only if you consider unnecessary use of pointers a problem. Try

vector<point> pt; // same as you had before
...
... pt.push_back(point(alpha...

I.e. without the pointers and without the 'new'.

V
 
E

Elzbieta Burnett

If I use solution proposed by John:
vector<point *> pt)
AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );

this seems to work.  Is there problem with this solution?

You have not told what problem you have, neither provided a sufficiently
complete example demonstrating the problem. Right now I cannot see how
using pointers instead of value objects could make anything better here,
this would only make working with the data more cumbersome and possibly
slower, in addition to creating a risk of memory leaks.

Cheers
Paavo


When iterating:

void AERODATA::Interpolate()
{
int i=0;
....
for( map<int, data>::iterator ii = AeroDOF.begin(); ii !=
AeroDOF.end(); ++ii)
{

A.Force = interpextrap( (ii->second).pt[0], //PT1
(ii->second).pt[3], //PT2
(ii->second).pt[1], //PT3
(ii->second).pt[4], //PT4
alphaNew,
betaNew );
i++;

}
....
}

I would set breakpoint on interpextrap(...) and examine alpha and beta
after many calls to AERODATA::Interpolate. These values would be
completely different from what is read from the file. When I used
pointers and allocated "points", this problem went away.

<Ella>
 
E

Elzbieta Burnett

If I use solution proposed by John:
vector<point *> pt)
AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );
this seems to work.  Is there problem with this solution?

You have not told what problem you have, neither provided a sufficiently
complete example demonstrating the problem. Right now I cannot see how
using pointers instead of value objects could make anything better here,
this would only make working with the data more cumbersome and possibly
slower, in addition to creating a risk of memory leaks.
Cheers
Paavo

When iterating:

void AERODATA::Interpolate()
{
  int i=0;
...
  for( map<int, data>::iterator ii = AeroDOF.begin(); ii !=
AeroDOF.end(); ++ii)
    {

      A.Force = interpextrap( (ii->second).pt[0],  //PT1
                                 (ii->second).pt[3],  //PT2
                                 (ii->second).pt[1],  //PT3
                                 (ii->second).pt[4],  //PT4
                                 alphaNew,
                                 betaNew );
      i++;

    }
...

}

I would set breakpoint on interpextrap(...) and examine alpha and beta
after many calls to AERODATA::Interpolate. These values would be
completely different from what is read from the file.  When I used
pointers and allocated "points", this problem went away.

<Ella>


BTW, ONLY time values to AeroDOF[].pt[] are set is when reading from
data file - one time. They should never change.

<Ella>
 
E

Elzbieta Burnett

If I use solution proposed by John:
vector<point *> pt)
AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );
this seems to work.  Is there problem with this solution?
You have not told what problem you have, neither provided a sufficiently
complete example demonstrating the problem. Right now I cannot see how
using pointers instead of value objects could make anything better here,
this would only make working with the data more cumbersome and possibly
slower, in addition to creating a risk of memory leaks.
Cheers
Paavo

When iterating:
void AERODATA::Interpolate()
{
  int i=0;
...
  for( map<int, data>::iterator ii = AeroDOF.begin(); ii !=
AeroDOF.end(); ++ii)
    {
      A.Force = interpextrap( (ii->second).pt[0],  //PT1
                                 (ii->second).pt[3],  //PT2
                                 (ii->second).pt[1],  //PT3
                                 (ii->second).pt[4],  //PT4
                                 alphaNew,
                                 betaNew );
      i++;

    }
...

I would set breakpoint on interpextrap(...) and examine alpha and beta
after many calls to AERODATA::Interpolate. These values would be
completely different from what is read from the file.  When I used
pointers and allocated "points", this problem went away.

BTW, ONLY time values to AeroDOF[].pt[] are set is when reading from
data file - one time. They should never change.

<Ella>


I am using:

$ g++ --version
g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)

<Ella>
 
E

Elzbieta Burnett

innews:da7c9ac3-565e- (e-mail address removed):
If I use solution proposed by John:
vector<point *> pt)
AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta,
Force [j] ) );
this seems to work.  Is there problem with this solution?
You have not told what problem you have, neither provided a
sufficiently complete example demonstrating the problem. Right now I
cannot see how using pointers instead of value objects could make
anything better here, this would only make working with the data more
cumbersome and possibly slower, in addition to creating a risk of
memory leaks.
Cheers
Paavo

When iterating:
void AERODATA::Interpolate()
{
  int i=0;
...
  for( map<int, data>::iterator ii = AeroDOF.begin(); ii
  !AeroDOF.end(); ++ii)
    {
      A.Force = interpextrap( (ii->second).pt[0],  //PT1
                                 (ii->second).pt[3],  //PT2
                                 (ii->second).pt[1],  //PT3
                                 (ii->second).pt[4],  //PT4
                                 alphaNew,
                                 betaNew );
      i++;

    }
...
}
I would set breakpoint on interpextrap(...) and examine alpha and beta
after many calls to AERODATA::Interpolate. These values would be
completely different from what is read from the file.  When I used
pointers and allocated "points", this problem went away.

These symptoms would be explained if you have a custom copy constructor
for the point class and which does not do a proper copy (the push_back()
operation may copy data around and would use this). Or maybe there is
some other error. Why do you check data only "after many calls" and not
immediately after reading in the file? Are you sure that the pt vector
actually contains at least 5 elements in the above code?

For catching unexpected data changes the data breakpoints are great, BTW.

hth
Paavo


I have conditional logic that end of interpextrap(...) to catch
problems. When I saw I had problem, I set conditional breakpoint in
GDB and examined these values. They should only be -6, 0, or 6. But
instead they were huge, ridiculous values.

<Ella>
 
E

Elzbieta Burnett

Sounds like you are reading uninitialized values. But note that gdb can
also report wrong values, especially in optimized code, do not trust the
gdb debugger 100%. Make sure to compile your code without optimization for
best debugging.

As you are on Linux you can also try to run the program with valgrind and
see if it spots any memory errors.

hth
Paavo

Just to make sure I understand all that's been said;

Original code:

struct point
{
double alpha, beta;
double Force;

point(double a, double b, double f) : alpha(a), beta(b), Force(f) {}

};

struct data
{
int dof;
int XYZ;
double X, Y, Z;
int node;
vector<point> pt;

};

map<int, data> AeroDOF;

AeroDOF[dof[j]].pt.push_back(point( alpha, beta,Force[j]));

This should work?

"Point" in:

AeroDOF[dof[j]].pt.push_back(point( alpha, beta,Force[j]));

is local to initialization routine but STL class (vector) should
create instance of "point" and copy contents from local "point" to new
entry in AeroDOF[].pt[] ? Vector values in AeroDOF[].pt[] should not
go away after call to initialize.

<Ella>
 
R

Rui Maciel

Ian said:
The evidence has led you the the correct conclusion! The [] operator on
std::vector does not allocate storage.

Is there any assurance made by the standard? From what I've gathered, the
C++ standard only specifies that std::vector must provide a couple of
operator[] instances which returns references to members, and that storage
management is handled automatically by the class.


Rui Maciel
 
N

none

Try:

struct data
{
int dof;
int XYZ;
double X, Y, Z;
int node;
vector<point *> pt;

};

AeroDOF[ dof[j] ].pt.push_back( new point( alpha, beta, Force
[j] ) );


Apart from creating a memory leak, this does nothing useful. Stick to
using values in the vector unless you have very good reasons not to.

Yannick
 
C

Calum

I thought that vector '[]' would create an instance of 'point' (like

map '[]'), call copy constructor and assign newly created entry to

point( alpha, beta, Force[j] ) in AeroDOF.pt.



Evidently this isn't true?


Exactly. std::vector::eek:perator[] never creates new items. However std::map::eek:perator[] behaves differently and does create new items.

You can use std::vector::at() which performs a bounds check on the vector and will throw an exception if the index is out of range. You must of course catch the exception.

You could also replace std::vector<point> with std::map<int,point>, so that points are allocated according to your expectations. However this is much less efficient.

Best to use std::vector::push_back(), resize() or pass the desired size of the vector to the constructor.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top