C ++使用vector作为类实例的静态容器

时间:2017-09-17 12:39:51

标签: c++ vector

我使用vector作为类的静态成员来计算类本身及其派生类的所有实例。但是当尝试调整容器大小时,我会从向量本身抛出一个堆栈溢出。

 // initialize static values:
    auto_ptr<HandleManager> ID3OBJ::HM = auto_ptr<HandleManager>(new HandleManager());
    auto_ptr<vector<shared_ptr<ID3OBJ>>> ID3OBJ::ObjectList = auto_ptr<vector<shared_ptr<ID3OBJ>>>(new vector<shared_ptr<ID3OBJ>>{});

我将静态成员初始化为空,如上所示。

// constructors:
        ID3OBJ::ID3OBJ(double x, double y, double z) : X(x), Y(y), Z(z), Handle(this->HM->addHandle()) { ObjectList->push_back(auto_ptr<ID3OBJ>(this));}
        ID3OBJ::ID3OBJ() : X(0), Y(0), Z(0), Handle(this->HM->addHandle()) { ObjectList->push_back(shared_ptr<ID3OBJ>(this));}

        Vector::Vector(double x, double y, double z) { X = x; Y = y; Z = z;
        ObjectList->push_back(auto_ptr<Vector>(this));}
        Vector::Vector() {
            X = 0; Y = 0; Z = 0;
            ObjectList->push_back(shared_ptr<Vector>(this));}

构造函数将任何新实例添加到实例列表中,该实例列表称为ObjectList。这是按预期工作的。

// deconstructors:
    ID3OBJ::~ID3OBJ()
    {
        string tempH = this->Handle;
        auto iter = ObjectList->end();
        if (ObjectList->size() == HM->assignedHandles())
        {
            iter = remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; });
        }
        ObjectList->erase(iter, ObjectList->end());
        this->HM->removeHandle(this->Handle);
    }

    Vector::~Vector()
    {
        string tempH = this->Handle;
        auto iter = ObjectList->end();
        if (ObjectList->size() == HM->assignedHandles())
        {
            iter=remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; });
        }
        ObjectList->erase(iter, ObjectList->end());
    }

据我所知,remove_if将在发生后用元素替换pred返回true的任何出现。意味着如果带有vec [3]作为参数的pred返回true,则vec [2]指向vec [4]而不是vec [3]。 因此需要擦除功能来缩短容器长度,但是一旦实现这种缩短就会发生错误。

标题文件:

// class-name:      ID3OBJ
    // Date:            30.01.2017
    // Version:         1.0
    // Description:     The class works as base class for all used 3D-Objects, and defines the operations all 3D-Objects have, namely the Direction in case of a vector, or origion in all other cases
    //

    class ID3OBJ
    {
    public:
        double X;
        double Y;
        double Z;
        static auto_ptr<vector<shared_ptr<ID3OBJ>>> ObjectList;

        ID3OBJ(double x, double y, double z);
        ID3OBJ();
        ~ID3OBJ();
        const string getHandle();

    protected:
        string Handle;
        static auto_ptr<HandleManager> HM;
    };

    // class-name:      I3DM
    // Date:            23.03.2017
    // Version:         1.0
    // Description:     The class works as Interface for classes which can do Vector-operations 
    //
    template <class T> class I3DM : public virtual ID3OBJ
    {
    public:
        using ID3OBJ::X;
        using ID3OBJ::Y;
        using ID3OBJ::Z;

        static auto_ptr<vector<shared_ptr<T>>> ObjectList;
    protected:
        using ID3OBJ::Handle;
        using ID3OBJ::HM;
    };
    // class-name:      Vector
    // Date:            30.01.2017
    // Version:         1.0
    // Description:     The class works as vector, it provides an interface to acces and modify vectors, aswell as most of the vector operations
    //
    class Vector : public virtual I3DM<Vector>
    { 
    public:
        using I3DM<Vector>::X;
        using I3DM<Vector>::Y;
        using I3DM<Vector>::Z;
        using I3DM<Vector>::ObjectList;
        Vector(double x, double y, double z);
        Vector();
        ~Vector();
    //I'm not sure if the protected members have to be provided aswell in the header file
    protected:
        using ID3OBJ::Handle;
        using ID3OBJ::HM;
    };

HM-头:

class HandleManager
    {
    public:
        HandleManager();
        const int assignedHandles();
        const string addHandle();
        void removeHandle(string hexstring);
    protected:
        int AssignedHandles;
        forward_list<int> FreeHandles;
        bool FreeHandlesAvailable;
    };

CPP:

const int string_to_hex(string s)
{
    int returnvalue;
    stringstream stream;
    stream << hex << s;
    stream >> returnvalue;
    return returnvalue;
}
HandleManager::HandleManager()
{
    this->FreeHandlesAvailable = false;
    this->AssignedHandles = 0;
}
const int HandleManager::assignedHandles()
{
    return this->AssignedHandles;
}
const string HandleManager::addHandle()
{
    string returnValue;
    if (this->FreeHandlesAvailable)
    {
        returnValue = int_to_hex(this->FreeHandles.front());
        this->FreeHandles.pop_front();
        this->AssignedHandles++;
        if (this->FreeHandles.empty()) { this->FreeHandlesAvailable = false; }
    }
    else
    {
        returnValue = int_to_hex(this->AssignedHandles);
        this->AssignedHandles++;
        if (this->AssignedHandles == 1) { returnValue = int_to_hex((int)0); }
        }
    return returnValue;
}
void HandleManager::removeHandle(string hexstring)
{
    this->FreeHandlesAvailable = true;
    this->FreeHandles.push_front(string_to_hex(hexstring));
    this->AssignedHandles--;
}

错误消息:

  

RVE.exe中0x00C01899处的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000001,0x01002F48)。发生

参数0x00000001很可能是一个句柄,有没有办法搜索具有内存地址的对象? (0x01002F48)

2 个答案:

答案 0 :(得分:2)

考虑从向量中删除ID3OBJ时会发生什么:

  1. 该向量将销毁auto_ptr<ID3OBJ> ...
  2. 会尝试销毁ID3OBJ ...
  3. 析构函数会尝试从向量中删除auto_ptr<ID3OBJ> ...
  4. 哪会破坏auto_ptr<ID3OBJ> ......我们会回到第1步。
  5. 此过程将递归,直到堆栈溢出。 Vector向量也是如此。 (Roger,Roger。你的矢量是什么,Victor?)

    标准库vector并非设计为可重入;如果vector的成员自行调用,则行为未定义。在您的情况下,vector::erase()通过您的析构函数间接调用自己。

    因此,您的程序行为未定义。

答案 1 :(得分:1)

auto_ptr&lt; ..&gt;(this),shared_ptr&lt; ..&gt;(this)或unique_ptr&lt; ..&gt;(this)永远不会正确并且等待发生错误。智能指针从已分配的内存中获取值,是指向对象的指针,您不知道它是如何产生的。您正在有效地执行以下操作,

int a;
auto_ptr< int > ap0( &a );   // certain death.
shared_ptr< int > ap1( &a ); // also certain death.

或同样糟糕,

auto_ptr< int > ap( new int );
auto_ptr< int > ap0( ap.get() );   // certain death.
shared_ptr< int > ap1( ap.get() ); // also certain death.

很难理解你想要实现的目标。如果你只想跟踪实例,你的向量肯定应该是原始指针。如果您的目的是内存管理,那么我无法从您的代码中了解这是如何工作的。