内存在两个函数调用之间切换

时间:2010-12-03 20:04:52

标签: c++

这是完全奇怪的。我有一些代码,我从文件中读取一些参数,并将它们存储在两个stl向量中。我有原子和残基,每个原子都有一个指向他残留物的指针。完成读取后,在声明变量后,看起来内存中的值发生了变化:

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

这是代码。我真的不知道我做错了什么

#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;

}

3 个答案:

答案 0 :(得分:13)

您所看到的是完全正常的行为 - 当您向向量添加新元素时,它可能会被调整大小,因此所有元素都会被复制到新的内存位置。

如果您需要保证现有元素不会在内存中移动,请使用其他容器,例如listset

答案 1 :(得分:1)

std :: vector会在需要更多空间时移动内存。它分配一个连续的内存块,当该块填满时,它会分配一个更大的块,将旧块中的所有元素复制到新块,释放旧块,然后继续。

为了防止您看到的行为,您可以执行以下任何操作来改善设计模式:

1)在main()中更改向量以存储指针而不是堆栈选项。这样,对象将始终位于内存中的相同位置。 2)通过实现复制构造函数和赋值运算符来更改类声明以允许深层复制 3)修改类heirarchy以消除类之间的循环依赖关系。你可以通过一个Residue类,一个Atom类和另一个将2映射到彼此的类来实现这一点。

最简单的选项是#1。你只需要确保正确清理内存。

答案 2 :(得分:0)

就像卡萨布兰卡所说,每当你的矢量扩展时,它就会改变物体在记忆中的位置。 如果你真的想使用向量而不是其他容器

1)你可以为你的矢量reserve一大块内存。如果您保证这些对象的数量不会超过某个范围,并且您不介意消耗那么多内存,那么请将您的向量设置为大。

2)使它们成为指针的向量。如果你有一个非常现代的编译器(例如gcc&gt; = 4.4),你甚至可以从C ++ 0x访问新的unique_ptr智能指针类,它允许你在stl容器中使用智能指针。这些对语言的重要补充。