Change memory between two function calls

This is totally strange. I have code in which I read some parameters from a file, and I store them in two stl vectors. I have atoms and residues, and each atom holds a pointer to its remainder. After reading, after declaring a variable, it looks like the values ​​in memory have changed:

 atoms [0] .resid: 0x96fc250
 & (atoms [0] .resid-> ID): 0x96fc25c
 ** (atoms [0] .resid-> ID): 1 **
 atoms [1] .resid: 0x96fc250
 & (atoms [1] .resid-> ID): 0x96fc25c
 ** (atoms [1] .resid-> ID): 1 **
 atoms [2] .resid: 0x96fc3ec
 & (atoms [2] .resid-> ID): 0x96fc3f8
 (atoms [2] .resid-> ID): 2
 atoms [3] .resid: 0x96fc3ec
 & (atoms [3] .resid-> ID): 0x96fc3f8
 (atoms [3] .resid-> ID): 2
 ---------------------------------------
 atoms [0] .resid: 0x96fc250
 & (atoms [0] .resid-> ID): 0x96fc25c
 ** (atoms [0] .resid-> ID): 891301941 **
 atoms [1] .resid: 0x96fc250
 & (atoms [1] .resid-> ID): 0x96fc25c
 ** (atoms [1] .resid-> ID): 891301941 **
 atoms [2] .resid: 0x96fc3ec
 & (atoms [2] .resid-> ID): 0x96fc3f8
 (atoms [2] .resid-> ID): 2
 atoms [3] .resid: 0x96fc3ec
 & (atoms [3] .resid-> ID): 0x96fc3f8
 (atoms [3] .resid-> ID): 2

Here is the code. I really don't know what I did wrong.

#define FT_GRO 1 using namespace std; class residue{ public: residue(){} residue(const residue& r){atoms=r.atoms; ID=r.ID; name= r.name;} residue(int n, string s) {name=s;ID=n;} public: vector<class atom*> atoms; int ID; string name; atom& addAtom(atom& a) { atoms.push_back(&a); return a;} }; class atom{ public: atom(){} atom(const atom& a){ID=a.ID,name=a.name,coord=a.coord,resid=a.resid ;} atom(const int anum, const string aname, const point3D& p, residue& res){coord=p; name=aname; resid=&res; ID=anum;} ~atom(){} public: point3D coord; int ID; string name; double distance(point3D& p) {return coord.distance(p);} double distance(atom& p) {return coord.distance(p.coord);} class residue* resid; }; int main(){ vector<atom> atoms; vector<residue> residues; double box1,box2,box3,x,y,z; char l[256]; int nr,na; string sr,sa; int lastResNum = -1; string lastResName(""); int nAtomsIn=4; for(int i =0; i<nAtomsIn;i++){ cin.getline(l,255); istringstream ssatm(l,ios::in); ssatm >> setw(5) >> nr >> setw(5) >> sr >> setw(5) >> sa >> setw(5) >>na >> setw(8) >> x >>setw(8) >> y >>setw(8) >> z; if (lastResNum!=nr || sr!=lastResName){ residues.push_back(residue(nr,sr)); } point3D p(x,y,z); atoms.push_back( atom(na,sa,p,residues.back()) ); residues.back().addAtom(atoms.back()); cout << "atoms["<<i<<"].resid :" << atoms[i].resid << endl; cout << "&(atoms["<<i<<"].resid->ID) :" << &(atoms[i].resid->ID) << endl; cout << "&(atoms["<<i<<"].resid->ID) :" << (atoms[i].resid->ID) << endl; lastResNum=nr; lastResName=sr; } cout << "---------------------------------------"<<endl; cin.getline(l,255); istringstream ssbox(l); ssbox >> setw(10) >> box1>>setw(10) >> box2>>setw(10) >> box3; for(int i =0; i<atoms.size();i++){ cout << "atoms["<<i<<"].resid :" << atoms[i].resid << endl; cout << "&(atoms["<<i<<"].resid->ID) :" << &(atoms[i].resid->ID) << endl; cout << "&(atoms["<<i<<"].resid->ID) :" << (atoms[i].resid->ID) << endl; } return 0; } 
+7
c ++
source share
3 answers

What you see is perfectly normal - when you add new elements to a vector, it can be changed, so all elements will be copied to a new memory location.

If you need a guarantee that existing items are not moved in memory, use another container, such as list or set .

+13
source share

std :: vector will move memory when more space is needed. It allocates a continuous block of memory, and when this block is full, it allocates a larger block, copies all the elements from the old block to the new one, frees the old block and moves.

To prevent the behavior you see, you can do any of several things to improve your project:

1) Change your vectors in main () to save pointers instead of stack options. Thus, the object will always be in one place in memory. 2) Modify class declarations to allow deep copies by executing the constructor and assignment operators 3) Modify your class hierarchy to remove the circular dependency between your classes. You can do this by having a Residue class, an Atom class, and another class that maps 2 to each other.

The simplest option would be # 1. You just need to make sure that you are clearing the memory correctly.

+1
source share

As casablanca said, whenever your vector expands, it changes where the objects are in memory. If you really want to use vectors instead of some other container

1) you can reserve large piece of memory for your vector. If you have a guarantee that the number of these objects will not exceed a certain limit, and you do not mind using this large memory, then make your vector so large.

2) make them pointer vectors. If you have a very modern compiler (e.g. gcc> = 4.4), you can even access the unique_ptr smart pointer class from C ++ 0x, which allows smart pointers to be used in stl containers. These are wonderful additions to the language.

0
source share

All Articles