2016-12-22 5 views
0

私はかなり奇妙な行動を観察しています。ベクトル内のアイテムへのポインタが不安定です。

#include <iostream> 
#include <vector> 
#include <stdexcept> 
#include "sparsepp.h" 


enum Version { 
    hg19, 
    hg38 
}; 


enum Base { 
    A, 
    T, 
    G, 
    C 
}; 


typedef struct { 
    Base ref; 
    float a; 
    float c; 
    float g; 
    float t; 
} SNV; 



class GenomeMap { 

private: 
    spp::sparse_hash_map<long, SNV*> * hg19_mapping; 
    spp::sparse_hash_map<long, SNV*> * hg38_mapping; 
    std::vector<SNV> values; 

public: 
    GenomeMap() { 

     hg19_mapping = new spp::sparse_hash_map<long, SNV*>; 
     hg38_mapping = new spp::sparse_hash_map<long, SNV*>; 

    } 

    void add(long hg19pos, long hg38pos, SNV value) { 
     values.push_back(value); 
     (*hg19_mapping)[hg19pos] = &(values.back()); 
     (*hg38_mapping)[hg38pos] = &(values.back()); 
    } 

    float get(Version version, long position, Base ref, Base alt) { 
     spp::sparse_hash_map<long, SNV*> * mapping = (version == hg19) ? hg19_mapping : hg38_mapping; 
     SNV* value = (*mapping)[position]; 

     if (!value || ref != value->ref) 
      return -1; 

     switch (alt) { 
      case A: 
       return value->a; 
      case C: 
       return value->c; 
      case G: 
       return value->g; 
      case T: 
       return value->t; 
     } 
     throw std::invalid_argument("Invalid arguments"); 
    } 

    ~GenomeMap() { 
     delete this->hg19_mapping; 
     delete this->hg38_mapping; 
    } 
}; 


int main(void) { 
    SNV value = {A, 0.1, 0.2, -1.0, 0.3}; 

    GenomeMap mapping; 
    mapping.add(1, 2, value); 
    mapping.add(2, 3, value); 
    std::cout << mapping.get(hg19, 1, A, T) << "\n"; 
    std::cout << mapping.get(hg19, 1, A, T) << "\n"; 
    std::cout << mapping.get(hg19, 2, T, G) << "\n"; 
    std::cout << mapping.get(hg19, 2, A, G) << "\n"; 
    std::cout << mapping.get(hg38, 1, A, T) << "\n"; 
    std::cout << mapping.get(hg38, 1, A, T) << "\n"; 
    std::cout << mapping.get(hg38, 2, T, G) << "\n"; 
    std::cout << mapping.get(hg38, 2, A, G) << "\n"; 

    return 0; 

} 

thisレポから採取された)sparsepp.hヘッダはハッシュマップsparse_hash_mapを定義:ここで最小の例です。私は私が得るほとんどの時間の代わりに、この出力

0.3 
0.3 
-1 
-1.1 
-1 
0.3 
-1 
-1.1 

をこの例を実行する場合:たまに

0.3 
0 
-1 
-1.1 
-1 
-1 
-1 
1.4013e-45 

2行目は、それがあるべきよう0.3です。私は信じています。私はsparse_hash_mapstd::mapと置き換えようとしましたが、何も変わりませんでした。

+0

値としてスマートポインタ(例: 'std :: unique_ptr')を使用しないのはなぜですか? –

+0

@πάνταῥεῖ私は長い間C++の厳密なC互換サブセットをコーディングしていましたので、 'std :: unique_ptr'については何がわかりません。私はもはやこの制限がありません。 –

+0

ここに行く:http://en.cppreference.com/w/cpp/memory –

答えて

4

あなたの問題は

void add(long hg19pos, long hg38pos, SNV value) { 
    values.push_back(value);     // <<<<======= HERE 
    (*hg19_mapping)[hg19pos] = &(values.back()); 
    (*hg38_mapping)[hg38pos] = &(values.back()); 
} 

あなたはvaluesに新しい値を押すと、あなたはすべての以前に割り当てられたポインタを無効にしています。あなたのオプションは以下のとおりです。

  • valuesに十分なスペースあなたがベクトルを再割り当て決して保証するために、追加を始める前に。これは、開始する前に最終サイズを知っている場合にのみ可能です。

  • インデックスをポインタではなくベクトルに格納します。インデックス(values.size()-1)は安定しています。

+0

ありがとうございました。 'insigned long'というインデックスを格納すると、64ビットポインタを格納するよりもメモリ効率が向上します。 –

+0

64ビットウィンドウを使用している場合のみ。他のすべてのプラットフォームでは(実際には)longとpointerは同じサイズです –

関連する問題