所以我试图牢牢掌握如何编写对象和指针的集合,而不会导致内存泄漏...我想做这样的事情......
class StackTest
{
public:
StackTest() : m_id(-1),
m_name("")
{ };
StackTest(const int id,
const std::string name) : m_id(id),
m_name(name)
{ };
void SomeFunctionThatCanPreformTasksOnTHISStackTest();
private:
const int m_id;
const std::string m_name;
}
class StackTestCollection
{
public:
void AddStackTest(const StackTest* test);
void SomeFunctionThatCanPreformTasksOnAllStackTests();
private:
std::vector<StackTest*> m_stack_tests;
}
然后我给集合添加了函数AddStackTest(并为集合和单独的StackTest创建了处理函数的函数)......
void StackTestCollection::AddStackTest(const StackTest* test)
{
m_stack_tests.push_back(test);
}
最后我的主要代码库......
// This scopes my_collection so that after the '}' my_collection should get deleted...
{
StackTestCollection my_collection;
my_collection.AddStackTest(new StackTest(0, "First Stack Test"));
my_collection.AddStackTest(new StackTest(0, "Second Stack Test"));
my_collection.AddStackTest(new StackTest(0, "Third Stack Test"));
}
现在我意识到我需要在存储在StackTestCollection中的StackTest指针上调用delete。我想我可以将它添加到StackTestCollection ....
~StackTestCollection()
{
for(auto &test : m_stack_tests)
{
delete test;
}
}
现在这让我问了几个问题......
1)这会导致程序在循环期间崩溃,因为我们正在删除堆中的数据,或者向量是否仍然稳定,因为堆栈中的指针仍然存在,但是是一个悬空指针... < / p>
2)我是否还需要对集合m_stack_tests向量运行删除?像这样......
delete m_stack_tests;
3)在我的主代码中,我创建了集合(StackTestCollection my_collection;),我的理解是我只需要用指针来控制垃圾....所以既然my_collection不是指针,我不会&# 39; t需要做一些事情......正确吗?
delete my_collection;
我想指出,此示例程序将在大型多线程服务器中运行,用户登录并分配自己的集合。 (因此每个用户在登录时都有自己的集合,并且在注销时也应该删除与用户相关的数据。)
另外,我没有使用C ++ 11,所以没有unique_ptr&#39; s。
答案 0 :(得分:2)
1:只要没有其他内容(例如另一个线程)在删除之后尝试访问堆资源,这不会导致问题。
2:如果你使用new来创建它,你只需要删除一些东西。
3:你说你不需要删除my_collection但是假设必须删除每个指针都是错误的,请考虑以下代码:
void Foo(int* ptr)
{
// do something
}
int i = 1234;
Foo(&i); // passing a pointer to i which is a stack based object
我建议使用智能指针来管理堆分配/解除分配,并避免使用new和delete。在您的情况下,您可以使用unique_ptr
的向量答案 1 :(得分:0)
将vector定义为您的类型的共享指针的向量。这将允许共享指针的析构函数在从向量中删除值时销毁对象。
答案 2 :(得分:0)
你可以做两件事:
std::vector<StackTest> m_stack_tests;
。无需内存处理。只需更改您的功能即可const StackTest&
或StackTest&&
。 std::vector<std::unique_ptr<StackTest>> m_stack_tests;
。现在,有内存处理,但unique_ptr
将为您处理一切,所以您不必担心它。 在这两种情况下,您都不必在任何地方写delete
,这很棒。你写它的方式,你将逐个delete
向量中的每个元素......但你不必须{{1}矢量本身。它不是delete
。
答案 3 :(得分:0)
通常,删除该内存 是安全的。
原因是指针是从外部源传入的,你不知道它们来自哪里(好吧,你做,但是当你编写接口时,你应该假装你不要T)。调用者负责管理内存。这就是为什么std::vector
在被破坏时不会为你释放内存的原因。
另一方面,你的班级不能安全地从指针的其他持有者那里删除它。这两个问题的解决方案是在AddStackTest
函数中获取数据的副本,但这可能效率低下。
当然,如果你在上面的评论中说,
/* This class takes ownership of the objects passed in, and will delete
them upon destruction. */
...现在你已经改变了规则,如果不是他们想要的话,调用者必须采取措施来复制对象。
有多种方法可以实现这种破坏。像你这样的显式析构函数会起作用,因此使你的向量使用std::unique_ptr
。
顺便提一下,您的AddStackTest
需要const StackTest*
,但是您存储StackTest *
,这似乎是错误的(编译器应警告您),除非您真的在那里制作副本。< / p>