我正在考虑这种情况,不是为了真正的实现,而是为了更好地理解指针是如何工作的。
class foo(){
foo();
~foo();
void doComplexThings(const std::vector<int*>& v){
int* copy;
for(int i = 0; i < v.size(); i++){
copy = v[i];
// do some stuffs
}
}
}
main(){
std::vector<int*> myVector; // suppose we have 100 elements
doComplexThings(myVector);
for(int i = 0; i < myVector.size(); i++){
delete myVector[i];
}
myVector.clear();
}
好的,我知道将v[i]
复制到另一个指针中是没有意义的,但我在想:copy
做内存泄漏?
执行doComplexThings()
后,copy
将继续存在并占用堆中的空间?
删除所有元素后,它将继续存在并指向释放的内存?
所以从逻辑上讲,如果我用复杂的对象做这些事情,我将继续用非引用对象占用内存吗?或copy
保存在堆栈中,因为我不使用新的?在doComplexThings结束时它会被删除吗?
我有点困惑,谢谢!
答案 0 :(得分:1)
执行此操作时,堆上没有分配额外的内存:
copy = v[i];
变量copy
指向与v[i]
相同的地址,但没有分配额外的数组,因此不存在内存泄漏。
处理这种情况的一个更好的方法是避免使用原始指针来支持C ++智能指针或容器:
std::vector<std::vector<int>> myVector;
现在您可以删除删除循环,这对于使用new int[length]
分配的数组执行此操作的方式不正确 - 它应该使用delete[]
代替:
delete[] myVector[i];
答案 1 :(得分:1)
对于C ++社区中的指针主题存在一些混淆。虽然智能指针已经添加到库中以减轻动态内存分配的问题,但原始指针并不过时。实际上,每当你想要在不拥有它的情况下检查另一个对象时,你应该使用一个引用或原始指针,具体取决于你的需要。如果您不清楚所有权的概念,请将对象视为另一个对象所拥有,如果后者负责事后清理(deleting
前者)。
例如,new
和delete
的大部分用途都应替换为以下内容(为简洁省略std
):
{
auto ptr_to_T = make_unique<T>(//constructor params);
do_stuff_with_smart_ptr(ptr_to_T);
do_stuff_with_T(*ptr_to_T);
do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()
请注意,如果T*
函数没有保留T*
的副本,那么do_stuff_with_T()
不需要智能指针的函数,因为它没有&#39 ; t影响对象的生命周期。保证对象在ClassThatNeedsSharedOwnership shared_owner;
{
auto ptr_to_T = make_shared<T>(//constructor params);
shared_owner.set_T(ptr_to_T);
// do a lot of stuff
}
// At this point ptr_to_T is destroyed, but shared_owner might keep the object alive
的返回点之后仍然存活,并且其函数签名表示它不通过获取原始指针来拥有对象。
另一方面,如果您需要将指针传递给允许保留指针并稍后引用它的对象,则不清楚何时需要销毁该对象,最重要的是由谁控制。这是通过共享指针解决的。
int
那么上述因素如何影响您的代码。首先,如果向量应该拥有(保持活动)它指向的unique_ptr<int>
,它需要保持shared_ptr<int>
或int
。如果它只是指向由其他东西持有的int*
,并且它们保证在向量被销毁之前存活,那么你可以使用delete
。在这种情况下,显然永远不需要for (auto copy : v){
// equivalent to your i-indexed loop with copy = v[i];
// as long as you don't need the value of i
do_stuff_to_int_ptr(copy);
// no delete, we don't own the pointee
}
,因为根据定义,您的向量和向量上的函数不负责清理!
最后,通过将循环更改为此(您在帖子中标记的C ++ 11),可以使代码更具可读性:
int
如果某个其他对象持有vector<int*>
并释放它们,或者它们在堆栈上但保证在指向它们的{{1}}的整个生命周期中保持活着,则这是唯一的。
答案 2 :(得分:0)
基本上你用C指针来解释问题导致引入C ++唯一和共享指针。如果将已分配指针的向量传递给不透明成员函数,则无法知道该函数是否挂起,因此您不知道是否删除指针。事实上,在你的例子中,你似乎并没有,#34; copy&#34;超出范围。
真正的答案是你根本不应该在C ++中使用分配的指针。 stl向量将作为一个更安全,更易于使用的malloc / new版本。然后你应该把它们传递给const&amp;防止功能改变它们。如果你确实需要一个已分配的指针,请创建一个unique_ptr(),然后你知道unique_ptr()是&#34;所有者&#34;记忆。