我正在观察一些非常奇怪的行为。这是最小的例子:
#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 repo)定义了散列图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
。我相信,我错过了一些非常愚蠢的东西。我尝试将sparse_hash_map
替换为STL中的std::map
,但没有任何改变。
答案 0 :(得分: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
中预留足够的空间,以确保永远不会重新分配向量。只有在开始之前知道最终尺寸时才可以这样做。
将 indices 存储到向量中,而不是指针。索引(values.size()-1
)将保持稳定。