列表、指针和局部变量

lists, pointers, and local variables

本文关键字:局部变量 指针 列表      更新时间:2023-10-16

这应该是一个简单的问题,但是我怎么也在网上找不到答案。

简单地说,创建一个对象并将其添加到指针列表中对我来说是行不通的——只要我试图用不同的方法访问列表中的项,它就会产生访问冲突。

两个问题:

做这件事的最好方法是什么?

2:随后,如果不使用指针列表,从列表中删除的最佳方法是什么?

int main( int argc, const char* argv[] )
{
    std::list<testClass*> list;
    addClass(list);
    std::cout << list.front()->a; //item added to list now longer accessible
}
void addClass(std::list<testClass*> list)
{
    testClass* c = new testClass();
    c->a = 1; c->b = 2;
    list.push_back(c); //item still accessible here
}

class testClass
{
public:
    int a;
    int b;
};

你需要通过引用传递你的list,你在这里通过值传递所以它正在复制容器并在该副本上工作:

void addClass(std::list<testClass*> list)

如果你像这样修改它,它应该像你想的那样工作:

void addClass(std::list<testClass*> &list)

第一个宏观错误是addClass应该取一个std::list<testClass*> &,这样它就可以操作main中包含的列表,而不是本地副本。

之后,整个设计必须更好地集中:

  • 既然testClass不是多态的(没有任何虚拟的),动态分配它们的意义是什么?让它们作为值直接包含在列表本身可能会更容易,有一个std::list<testClass>

  • 还是……如果您需要动态分配,您还必须考虑释放,否则您将泄漏内存:如果列表包含指针,它将销毁指针,而不是它们指向的内容。

现在,让我们沿着这两条轨道:

将对象作为值处理

你需要一种方法从给定的值构造一个testClass对象。

class testClass
{
public:
    testClass(int a_, int b_) 
       :a(a_), b(b_)
    {}
    int a;
    int b;
};

现在你可以

void addClass(std::list<testClass>& list)
{
    list.emplace_back(1,2);
}

int main()
{
    std::list<testClass> list;
    addClass(list);
    std::cout << list.front().a; 
}

注意一些*是如何消失的!

动态处理对象

可以用new创建,但是你必须注意删除。

一种方法是从列表中删除点:就在main中的}之前…

for(auto p : list) delete p;

this将遍历整个列表,并对每个指针调用delete,从而释放(并销毁)您用new分配的对象。

注意:这不会使列表为空:列表中仍然包含指针,它们只是指向无效的地址。指针将在main

的出口被列表释放。

另一种方法是不使用普通指针,而是使用智能指针,当它们被销毁时,它会删除自己的内容。

这需要一个std::list<std::unique_ptr<testClass> >作为容器,这样你就可以

void addClass(std::list<std::unique_ptr<testClass> >& list)
{
    list.emplace_back(new testClass(1,2)); 
}

现在,当main退出时,列表被自己的元素(智能指针)销毁,然后delete new分配的对象。