指向向量中项目的指针是不稳定的。
Posted
技术标签:
【中文标题】指向向量中项目的指针是不稳定的。【英文标题】:Pointers to items in a vector are unstable. 【发布时间】:2016-12-22 09:15:21 【问题描述】:我观察到一些非常奇怪的行为。这是最小的例子:
#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
替换 sparse_hash_map
,但没有任何改变。
【问题讨论】:
为什么不使用智能指针(例如std::unique_ptr
)作为值?
@πάνταῥεῖ 我一直在用严格的 C 兼容的 C++ 子集进行编码,所以我不知道 std::unique_ptr
是关于什么的。不过,我不再有这个限制了。
给你:en.cppreference.com/w/cpp/memory
不要存储指向向量元素的指针。当底层存储被重新分配时,它们变得无效。
@StephanLechner 据我所知,vector.back
返回的是引用,而不是副本。
【参考方案1】:
你的问题是
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
) 将保持稳定。
【讨论】:
非常感谢。将索引存储为insigned long
甚至比存储 64 位指针更节省内存。
仅当您使用 64 位窗口时。在所有其他平台上(实际上)长和指针大小相同以上是关于指向向量中项目的指针是不稳定的。的主要内容,如果未能解决你的问题,请参考以下文章