获取指向矢量元素的指针

时间:2017-05-25 22:22:39

标签: c++ pointers vector

我遇到了一个我不太明白的问题:

我正在使用

创建一个对象Edge
edge_vec1.push_back(Edge(src,dest));

然后我想在一个单独的向量中保留指向此Edge的指针:

edge_vec2.push_back(&edge_vec1.back());

但是,一旦我添加了第二个Edge对象,指向edge_vec2中第一个Edge的指针就会失效(获取一些随机数据)。是因为edge_vec2中的指针实际指向edge_vec1中的某个位置,而不是底层元素?我可以通过在堆上创建我的Edge对象来避免这种情况,但我想了解发生了什么。

谢谢。

3 个答案:

答案 0 :(得分:3)

当向元素添加新元素时,可以重新分配向量。因此,指向向量元素的指针的先前值可能无效。

您应该首先为矢量保留足够的内存以防止重新分配。

➜  ~ jhipster --help

  Usage: jhipster [command] [options]


  Commands:

    app                       Create a new JHipster application based on the selected options
    aws                       Deploy the current application to Amazon Web Services
    ci-cd                     Create pipeline scripts for popular Continuous Integration/Continuous Deployment tools
    client                    Create a new JHipster client-side application based on the selected options
    cloudfoundry              Generate a `deploy/cloudfoundry` folder with a specific manifest.yml to deploy to Cloud     Foundry
    docker-compose            Create all required Docker deployment configuration for the selected applications
    entity [name]             Create a new JHipster entity: JPA entity, Spring server-side components and Angular     client-side components
    export-jdl [jdlFile]      Create a JDL file from the existing entities
    heroku                    Deploy the current application to Heroku
    import-jdl [jdlFiles...]  Create entities from the JDL file passed in argument
    info                      Display information about your current project and system
    kubernetes                Deploy the current application to Kubernetes
    languages [languages...]  Select languages from a list of available languages. The i18n files will be copied to the /    webapp/i18n folder
    openshift                 Deploy the current application to OpenShift
    rancher-compose           Deploy the current application to Rancher
    server                    Create a new JHipster server-side application
    service [name]            Create a new Spring service bean
    upgrade                   Upgrade the JHipster version, and upgrade the generated application
    completion                Print command completion script

  Options:

    -h, --help     output usage information
    -d, --debug    enable debugger
    -V, --version  output the version number

  For more info visit https://jhipster.github.io

➜  ~     

答案 1 :(得分:3)

来自http://en.cppreference.com/w/cpp/container/vector/push_back

  

如果new size()大于capacity(),则所有迭代器和引用(包括last-the-end迭代器)都将失效。否则只有过去的迭代器无效。

当您向其添加项目时,依赖于vector中对象的指针/引用是一个坏主意。最好存储索引的值,然后使用索引从vector中获取项目。

edge_vec2.push_back(edge_vec1.size()-1);

稍后,您可以使用:

edge_vec1[edge_vec2[i]]

表示某些有效值i

答案 2 :(得分:1)

std :: vector的要求是底​​层存储是一个连续的内存块。因此,当您要插入元素但当前分配的块不足以容纳其他元素时,向量必须重新分配其所有元素。发生这种情况时,所有迭代器和指针都会失效,因为完整的块被重新分配(移动)到完全不同的内存部分。

成员函数容量可用于查询可插入的最大元素数量,而无需重新分配底层内存块。查询此示例代码:

std::vector<int> vec;
for(int i = 0; i < 1000; i++) {
     bool still_has_space = vec.capacity() > vec.size();
     if (!still_has_space) std::cout << "Reallocating block\n"; 
     vec.push_back(i);
}

如果不需要连续内存布局的强保证,最好使用std :: deque而不是std :: vector。它允许在任一端推动元件而不移动任何其他元素。您可以通过稍微更差的迭代速度进行交易。

 std::deque<int> deq;
 std::vector<int*> pointers;
 for(int i = 0; i < 1000; i++) {
      deq.push_back(i);
      pointers.push_back(&deq.back());
 }
 for(auto p : pointers) std::cout << *p << "\n"; // Valid