C++ 从列表中自动添加和删除对象

C++ 从列表中自动添加和删除对象,c++,constructor,shared-ptr,weak-ptr,C++,Constructor,Shared Ptr,Weak Ptr,我有课。当这个类被实例化时,我希望实例被添加到一个列表中。删除对象时,我希望将其从列表中删除 class MyClass { private: static std::list<MyClass*> mylist; std::list<MyClass*>::iterator mylink; // disable copy constructor and assignment operator MyClass(const MyClass&am

我有课。当这个类被实例化时,我希望实例被添加到一个列表中。删除对象时,我希望将其从列表中删除

class MyClass
{
private:
    static std::list<MyClass*> mylist;
    std::list<MyClass*>::iterator mylink;

    // disable copy constructor and assignment operator
    MyClass(const MyClass& other);
    MyClass& operator = (const MyClass& other);

    void AddList()
    {
        mylink = mylist.insert(mylist.end(), this);
    }

    void RemoveList()
    {
        mylist.erase(mylink);
    }

public:
    MyClass()
    {
        AddList();
    }

    virtual ~MyClass()
    {
        RemoveList();
    }

    static std::list<MyClass*>::iterator GetAllObjects_Begin()
    {
        return mylist.begin();
    }

    static std::list<MyClass*>::iterator GetAllObjects_End()
    {
        return mylist.end();
    }

    virtual std::string ToString() const
    {
        return "MyClass";
    }
};

class Derived : public MyClass
{
    virtual std::string ToString() const
    {
        return "Derived";
    }
};

std::list<MyClass*> MyClass::mylist;


int main()
{
    std::vector<MyClass*> objects;
    objects.push_back(new MyClass);
    objects.push_back(new MyClass);
    objects.push_back(new Derived);
    objects.push_back(new MyClass);

    for (std::list<MyClass*>::const_iterator it = MyClass::GetAllObjects_Begin(), end_it = MyClass::GetAllObjects_End(); it != end_it; ++it)
    {
        const MyClass& obj = **it;
        std::cout << obj.ToString() << "\n";
    }

    while (! objects.empty())
    {
        delete objects.back();
        objects.pop_back();
    }
}
所以我给这个对象一个指向它自己的共享指针。然后我有一个指向这些共享指针的弱指针列表。创建对象时,它会创建一个指向自身的共享指针,生成一个指向该对象的弱指针,并将该弱指针放入列表中

当对象被销毁时,共享指针也会被删除。每当我尝试访问列表中的成员时,我都会确保该成员未过期,并且其使用计数不为0。尽管如此,当列表成员被销毁时,我仍然崩溃。为什么?我能绕开它吗?这是我的SSCCE:

#包括
#包括
#包括
课堂测试
{
私人:
std::共享的ptr自我;
公众:
int-val;
测试(int集);
测试(测试和复制)=删除;//确保没有问题
//删除了一个错误的实例
};
病媒试验;
测试::测试(int集):
瓦尔(套)
{
this->self=std::shared_ptr(this);
测试。推回(std::weak_ptr(this->self));
}
无效打印测试()
{
for(自动i=tests.begin();i!=tests.end();i++)
{
如果(i->use_count()==0 | i->expired())
{
测试。擦除(i);
继续;
}
std::cout lock()->val这行有问题:

指向已擦除元素的迭代器无效,您不能再增加它。幸运的是,
erase
返回一个新的迭代器,您可以使用:

auto i = tests.begin();
while (i != tests.end())
{
    if (i->use_count() == 0 || i->expired())
    {
        i = tests.erase(i);
    }
    else {
        std::cout << i->lock()->val << std::endl;
        ++i;
    }
}
auto i=tests.begin();
while(i!=tests.end())
{
如果(i->use_count()==0 | i->expired())
{
i=测试。擦除(i);
}
否则{
std::cout lock()->val这行有问题:

指向已擦除元素的迭代器无效,您不能再增加它。幸运的是,
erase
返回一个新的迭代器,您可以使用:

auto i = tests.begin();
while (i != tests.end())
{
    if (i->use_count() == 0 || i->expired())
    {
        i = tests.erase(i);
    }
    else {
        std::cout << i->lock()->val << std::endl;
        ++i;
    }
}
auto i=tests.begin();
while(i!=tests.end())
{
如果(i->use_count()==0 | i->expired())
{
i=测试。擦除(i);
}
否则{

std::cout lock()->val您的问题在于如何创建自指针:

 this->self = std::shared_ptr<test>(this);
this->self=std::shared\u ptr(this);
根据

当T不是数组类型时,构造一个拥有指针p的共享_ptr。 ... p必须是指向一个对象的指针,该对象是通过C++新表达式分配的,或者是0<p/p。 所以问题是
shared_ptr
正在获取堆栈对象的所有权,因此当对象被销毁时(以及
shared_ptr
一起),
shared_ptr
正在尝试
删除堆栈上的对象。这是无效的


对于您的用例,如果您希望
test
s比
向量
寿命长,那么您可能只需要存储
这个

,您的问题在于如何创建自指针:

 this->self = std::shared_ptr<test>(this);
this->self=std::shared\u ptr(this);
根据

当T不是数组类型时,构造一个拥有指针p的共享_ptr。 ... p必须是指向一个对象的指针,该对象是通过C++新表达式分配的,或者是0<p/p。 所以问题是
shared_ptr
正在获取堆栈对象的所有权,因此当对象被销毁时(以及
shared_ptr
一起),
shared_ptr
正在尝试
删除堆栈上的对象。这是无效的


对于您的用例,如果您希望
test
s比
向量
更长寿,那么您可能只需要存储
这个

我认为OP对其原始问题的解决方案感兴趣,即使它使用的方法与他尝试的方法不同。下面是一个如何将对象添加到全局列表的简单示例当它被构造时,在它被删除时将其删除。需要记住的一点是:您必须在添加到基类的每个构造函数中调用AddList。我不知道您是否希望该列表在类外部可访问,因此我添加了getter函数以将非常量迭代器返回到列表

class MyClass
{
private:
    static std::list<MyClass*> mylist;
    std::list<MyClass*>::iterator mylink;

    // disable copy constructor and assignment operator
    MyClass(const MyClass& other);
    MyClass& operator = (const MyClass& other);

    void AddList()
    {
        mylink = mylist.insert(mylist.end(), this);
    }

    void RemoveList()
    {
        mylist.erase(mylink);
    }

public:
    MyClass()
    {
        AddList();
    }

    virtual ~MyClass()
    {
        RemoveList();
    }

    static std::list<MyClass*>::iterator GetAllObjects_Begin()
    {
        return mylist.begin();
    }

    static std::list<MyClass*>::iterator GetAllObjects_End()
    {
        return mylist.end();
    }

    virtual std::string ToString() const
    {
        return "MyClass";
    }
};

class Derived : public MyClass
{
    virtual std::string ToString() const
    {
        return "Derived";
    }
};

std::list<MyClass*> MyClass::mylist;


int main()
{
    std::vector<MyClass*> objects;
    objects.push_back(new MyClass);
    objects.push_back(new MyClass);
    objects.push_back(new Derived);
    objects.push_back(new MyClass);

    for (std::list<MyClass*>::const_iterator it = MyClass::GetAllObjects_Begin(), end_it = MyClass::GetAllObjects_End(); it != end_it; ++it)
    {
        const MyClass& obj = **it;
        std::cout << obj.ToString() << "\n";
    }

    while (! objects.empty())
    {
        delete objects.back();
        objects.pop_back();
    }
}
class-MyClass
{
私人:
静态std::列表mylist;
std::list::迭代器mylink;
//禁用复制构造函数和赋值运算符
MyClass(常数MyClass和其他);
MyClass和运算符=(常量MyClass和其他);
void AddList()
{
mylink=mylist.insert(mylist.end(),this);
}
void RemoveList()
{
mylist.erase(mylink);
}
公众:
MyClass()
{
AddList();
}
虚拟~MyClass()
{
RemoveList();
}
静态std::list::迭代器getAllObject_Begin()
{
返回mylist.begin();
}
静态std::list::迭代器getAllObject_End()
{
返回mylist.end();
}
虚拟std::string ToString()常量
{
返回“MyClass”;
}
};
派生类:公共MyClass
{
虚拟std::string ToString()常量
{
返回“派生”;
}
};
std::list MyClass::mylist;
int main()
{
向量对象;
对象。推回(新MyClass);
对象。推回(新MyClass);
对象。推回(新派生);
对象。推回(新MyClass);
对于(std::list::const_iterator it=MyClass::GetAllObjects_Begin(),end_it=MyClass::GetAllObjects_end();it!=end_it;++it)
{
const MyClass&obj=**it;

std::cout我认为OP对解决其原始问题感兴趣,即使它使用的方法与他尝试的方法不同。下面是一个简单的示例,说明如何在构造对象时将其添加到全局列表,并在删除对象时将其删除。需要记住的一点是:必须在添加到b的每个构造函数中调用AddList我不知道你是否想要