2010-12-03 8 views
7

私はファイルからいくつかのパラメータを読み、2つのstlベクトルでそれらを格納するいくつかのコードを持っています。私は原子と残余を持ち、すべての原子は残余を指し示しています。読み込みが終わると、変数を宣言した後、メモリ内の値が変更されたように見えます。メモリが2つの関数間で変更されると、これは全く変わっています。

 
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; 

} 

答えて

13

間違っていたかわからない - あなたはベクトルに新しい要素を追加するとき、それはすべての要素がコピーされているため、リサイズされるかもしれません新しいメモリロケーション。

既存の要素がメモリ内に移動しないようにするには、listまたはsetなどの別のコンテナを使用します。

+3

新しい要素をコンテナに追加するときにコピーを防ぐには、 'vector'ではなく' list'を使用してください。 – chrisaycock

+0

@chrisaycock:私はちょうどそれを追加しようとしていた。 :) – casablanca

+1

またはベクトルがそれらを移動しないことを確認します。ベクトルが現在の領域をオーバーフローさせないようにする場合(たとえば、reserve()のサイズを変更して)、オブジェクトは移動されません。 –

1

std :: vectorは、スペースが必要なときにメモリを移動します。それは連続したメモリブロックを割り当て、そのブロックがいっぱいになると大きなブロックを割り当て、古いブロックから新しいブロックにすべての要素をコピーし、古いブロックを解放して移動します。あなたが見ている行動を防止するために

、あなたのデザインのパターを改善するためのいくつかのいずれか行うことができます。

1)の代わりに、スタックのオプションのポインタを格納するために)(メインであなたのベクトルを変更します。この方法では、オブジェクトは常にメモリ内の同じ場所に置かれます。 2)コピーコンストラクタと代入演算子を実装してディープコピーを許可するようにクラス宣言を変更します 3)クラス間の循環依存関係を削除するようにクラス階層を変更します。これは、Residueクラス、Atomクラス、および2を互いにマップする別のクラスを持つことで実行できます。

最も簡単なオプションは#1です。あなたはちょうどあなたが正しくメモリをきれいにすることを確認する必要があります。

0

casablancaのように、ベクトルが展開されるたびにオブジェクトがメモリ内にある場所が変更されます。 実際にベクトルを他のコンテナの代わりに使用したい場合は

)あなたのベクトルの大きなメモリをreserveにすることができます。これらのオブジェクトの数が特定の範囲を超えないことが保証されていて、その多くのメモリを使い切ってもかまわない場合は、ベクターを大きくしてください。

2)ポインタのベクトルにします。非常に最新のコンパイラ(たとえばgcc> = 4.4)を使用している場合、C++ 0xの新しいunique_ptrスマートポインタクラスにアクセスすることもできます。これにより、stlコンテナにスマートポインタを使用できます。これらの言語へのこれらの大きな追加。

関連する問題