c++ - 指向 vector 中项目的指针是不稳定的。

标签 c++ class struct

我观察到一些非常奇怪的行为。这是最小的例子:

#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 header (取自 this repo)定义了 HashMap 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,但没有任何改变。

最佳答案

你的问题是

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 中保留足够的空间,以确保永远不会重新分配 vector 。这只有在您开始之前就知道最终尺寸的情况下才有可能。

  • 索引存储到 vector 中,而不是指针。索引 (values.size()-1) 将保持稳定。

关于c++ - 指向 vector 中项目的指针是不稳定的。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41279515/

相关文章:

c++ - mingw32 上的 libtar.h

c++ - 为什么不能通过名称打印成员函数的地址?

c - 将结构保存在 C 中的数据库文件中

c++ - 继承和默认构造函数的一些问题

c# - 找不到命名空间或类型

arrays - Golang graphql 使用子图迭代 map

c++ - ((MPI_Datatype)1) 在 C++ 中是什么意思?

c++ - 为什么 select() 返回 1 而 recv() 返回 0?

c++ - 如何从成员初始化列表中调用随机生成器的seed_seq构造函数?

按钮元素上的 HTML 多个类