2016-12-22 125 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; 

} 

sparsepp.h頭部(從this回購截取)定義的散列映射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 

有一次,第二行是0.3理所應當的。我相信,我錯過了一些非常愚蠢的東西。我試圖用STL替換和std::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.size()-1)將保持穩定。

+0

非常感謝。將索引存儲爲'insigned long'甚至會比存儲64位指針更具有內存效率。 –

+0

僅當您使用64位窗口時。在所有其他平臺上(實際上)長和指針是相同的大小 –