2017-10-06 76 views
2

我正在创建一个由分支组成的树。为了我的工作目的,我需要跟踪分支,为了做到这一点,我想将它们存储在向量列表中。我将vector-list作为全局变量存储在此文件中,因为我想在构造函数和下面的代码片段中显示的函数中使用它。如何将矢量列表存储为全局变量?

这里比较棘手的部分是,我收到一条错误消息(在Visual Studio 2013中运行),据我所知可能与迭代器没有正常工作有关。每当我调用branchList.push_back(root)和branchList.resize()时都会出现错误消息。 branchList.size()不会导致错误。

所以我的问题是:我错过了什么/不理解,使这项工作?如果我要放置向量branchList;在构造函数的开始,一切都按预期工作。但是这对我没有帮助,因为我以后需要在其他功能中使用它。

我正在使用的文件中的相关代码片段。

skeletonBuilder.h:

class TreeSkeleton { 

public: 
    TreeSkeleton(); 
    void growTree(); 
}; 

skeletonBuilder.cpp:

#include "skeletonBuilder.h" 
#include <cstdint> 
#include <vector> 


typedef struct branch { 
    branch *parent; 
    vec3 position; 
    vec3 direction; 
} branch; 

//used by constructor + "treeGrow" function 
std::vector<branch> branchList = {}; 

TreeSkeleton::TreeSkeleton() { 
    //instantiate the tree root as a starting position. 
    branch root; 
    root.parent = NULL; 
    root.position = vec3(0, 0, 0); 
    root.direction = vec3(0, 1, 0); 

    branchList.size(); //works fine 
    branchList.resize(100); //Crashes here 
    branchList.push_back(root); //Crashes here 
} 

TreeSkeleton::growTree() { 
    //pushing more branches to branchList 
} 

main.cpp中:

#include "skeletonBuilder.h" 

TreeSkeleton tree; 

int main(int argc, char *argv[]) { 

    return 0; 
} 

该错误消息我得到:

Unhandled exception at 0x00507077 in OpenGL_project_Debug.exe: 0xC0000005: Access violation reading location 0x40EAAAB4. 

错误消息带我到下面的代码片断在一个名为“矢量”文件:

#if _VECTOR_ORPHAN_RANGE 
void _Orphan_range(pointer _First, pointer _Last) const 
    { // orphan iterators within specified (inclusive) range 
    _Lockit _Lock(_LOCK_DEBUG); 
    const_iterator **_Pnext = (const_iterator **)this->_Getpfirst(); 
    if (_Pnext != 0) 
     while (*_Pnext != 0) //<----------------This is the row that it gets stuck on 
      if ((*_Pnext)->_Ptr < _First || _Last < (*_Pnext)->_Ptr) 
       _Pnext = (const_iterator **)(*_Pnext)->_Getpnext(); 
      else 
       { // orphan the iterator 
       (*_Pnext)->_Clrcont(); 
       *_Pnext = *(const_iterator **)(*_Pnext)->_Getpnext(); 
       } 
    } 
+0

请复制粘贴你得到 – UnholySheep

回答

1

全局对象的初始化顺序没有实现文件之间的保证。没有办法知道,而main.cppskeletonBuilder.cpp的全局将首先被初始化。在你的情况下,TreeSkeleton treestd::vector<branch> branchList之前被初始化,这会导致你的问题。 TreeSkeleton的构造函数必须使用未初始化的branchList,这是未定义的行为。解决方案是放置您的全局变量,以保证订单

一个解决方案是使branchList为局部静态变量。这些变量保证在第一次遇到时被初始化。

例如:

class TreeSkeleton { 

public: 
    TreeSkeleton(); 
    void growTree(); 

private: 
    static std::vector<branch> & getBranches(); 
}; 

std::vector<branch> & TreeSkeleton::getBranches() 
{ 
    // branchList is initialized the first time this line is encountered 
    static std::vector<branch> branchList; 
    return branchList; 
} 

TreeSkeleton::TreeSkeleton() 
{ 
    //instantiate the tree root as a starting position. 
    branch root; 
    root.parent = NULL; 
    root.position = vec3(0, 0, 0); 
    root.direction = vec3(0, 1, 0); 

    auto & branchList = getBranches(); 
    branchList.size(); 
    branchList.push_back(root); // Should be fine now 
} 
+0

更妙的是完全消除全局的*确切*错误消息。我没有看到这些变量需要全局化的好理由,而不是树中包含的向量(作为成员或静态,如果它在所有树之间共享)以及在主函数内部声明的树。 –

+0

好的,我明白你在说什么,并会尝试使用你写的功能。然而,一个问题是struct分支已经在.cpp文件中实现,这意味着“静态std :: vector ...”不知道“分支”是什么。 –

+0

如果您需要,您可以将静态成员函数更改为实现文件中的自由函数。 –