当我删除指针的指针时会发生啥?

Posted

技术标签:

【中文标题】当我删除指针的指针时会发生啥?【英文标题】:What happens when I delete a pointer of pointer?当我删除指针的指针时会发生什么? 【发布时间】:2017-03-08 15:34:14 【问题描述】:

我有一个像 std::vector<AnyObject*> myVector; 这样的向量,我想删除向量中的一个元素,而不改变其他元素的位置。我怎样才能做到这一点 ?我有两个解决方案,告诉我它们是否好:

AnyObject* initial;
std::vector<AnyObject*> myVector(10, initial);
AnyObject* object = myVector.at(4);
delete object;

AnyObject* initial;
std::vector<AnyObject*> myVector(10, initial);
delete myVector.at(4);

当我删除 object 时,第一个解决方案会发生什么?我还要删除向量中的指针还是只删除 object

编辑:

当我写AnyObject* initial; 时,我知道initial 没有初始化,我只想说如果我有一个初始化指针向量并且如果我想删除一个指针而不改变其他指针的位置会发生什么。

EDIT2:

对于问题的上下文,我有一个类PointCloud 和另一个类SubsampledPointCloud。我想用最小云的相同大小对我的所有云进行二次采样,所以在我的二次采样点云中,我至少有一个云的点云大小相同。所以为了构建我的SubsampledPointCloud 向量,我初始化了一个PointCloud 向量,一个变量minPointCloudSize 等于我的点云中的最小大小,我这样做:

std::vector<SubsampledPointCloud*> subcloud(clouds.size());
for (std::size_t i = 0; i < clouds.size(); i++) 
    if (clouds.at(i).size() > minPointCloudSize)
        subcloud.at(i) = subPointCloud(clouds.at(i)); //subPointCloud is a function 
                                                      //that return a SubsampledPointCloud*
    else
        subcloud.at(i) = clouds.at(i);

后来,我不需要这个二次采样的点云,所以我将删除所有这些,除非子云与原始云的大小相同。 当然,SubsampledPointCloud 继承自 PointCloud

【问题讨论】:

你可以这样做,但你会在向量中留下一个无效指针,我会说,也许不是那么好但也不非法(显然你应该初始化 initial 以及一些程序员老兄说)。 由于您没有初始化initial,因此向量中的所有元素都将具有相同的indeterminate 值,而delete 是不能初始化的值。如果你想用十个空指针初始化向量,只需让它们被默认初始化(例如std::vector&lt;AnyObject*&gt; myVector(10);)。 哦,如果你初始化initial,那么所有十个元素都将指向同一个内存,这意味着如果你delete一个,那么所有其他指针都会变成无效。 最后,如果你使用指针,你必须记住 delete 不会修改实际指针本身,所以如果你 delete 向量中的指针它不会自动设置为 @ 987654345@ 但保留其(现在无效)值。 听起来像XY-question。你真正想要达到的目标是什么?如果它们在使用后会死掉,为什么还要使用指针而不是实际的对象?对于多态?你能给我们一些背景信息,比如 Car 或 Student 等有意义的名字吗?为什么不使用 shared_ptr 或 unique_ptr? 【参考方案1】:

我有两个解决方案,告诉我它们是否好

您的两个解决方案都有 UB - 您从未初始化的变量 initial 中读取。如果您设法将正确初始化的指针放入您的向量,那么两种变体将具有相同的效果 - 如果向量中的第五个指针不等于nullptr,则它指向的对象将被销毁并释放内存。你应该明白 delete 不会修改传递给它的参数,所以调用 delete 不会改变指针本身,除非它不等于 nullptr 你会在向量中留下悬空指针。为它重新分配新价值或在此之后避免使用它将是你的工作。或者将其从调用向量方法的向量中移除。

我还要删除向量中的指针还是只删除对象?

您只是删除对象,指针将具有完全相同的值,即指向对象曾经所在的内存。

【讨论】:

【参考方案2】:

在这两种情况下都存在分段错误,因为您实际上没有创建任何 AnyObject,只有空指针向量。

一般来说,如果你有一个指向对象的指针向量,你可以通过删除对象来删除对象,然后将指针设置为空,表示它不指向对象。

使用您的示例,掩盖您尚未创建任何对象的事实:

AnyObject* initial;
std::vector<AnyObject*> myVector(10, initial);
delete myVector[4];
myVector[4] = 0;

【讨论】:

"只有空指针向量。"这是不正确的,如果这是真的,删除第五个元素是安全的。 initial 不是 nullptr 另外,delete nullptr 完全有效。 @Gill Bates:是的,你是对的,它是一个未初始化指针的向量。我马虎了。我的观点是删除未初始化的指针是不安全的,我在段错误注释中提到了这一点。【参考方案3】:
std::vector<AnyObject*> myVector(10, initial);

此语句将使用 10 个initial 对象初始化向量。 initial 是内存引用,当您 delete 它释放分配给 initial 对象的内存时,在这两种情况下都会使所有向量元素指向无效的内存位置。如果您在两种情况下都尝试在删除后访问它,则行为将是未定义的。

【讨论】:

是的,我没有看到这个,但是如果向量中的元素都不同,会发生什么? 在这种情况下,它会产生相同的影响,即您删除的是对象而不是指针。它将使该向量元素指向无效的内存位置。 如果你删除了一个指针,即向量的一个元素,如果它们没有指向相同的内存位置,它不会对其他元素产生影响【参考方案4】:

你的前提是有缺陷的。你不应该使用原始指针来处理对象的生命周期,使用std::unique_ptr(或者std::shared_ptr,如果生命周期真的是共享的

那么你的例子看起来像

std::vector<std::unique_ptr<AnyObject> > myVector(10, nullptr);
// other code
myVector[index] = make_unique<AnyObject>(args...);
// other code
myvector[other_index].reset(nullptr);

【讨论】:

以上是关于当我删除指针的指针时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

当我在 NULL 对象指针上调用成员函数时会发生啥? [复制]

当我取消引用指针并将值分配给某个变量时,内存会发生啥?

(c++) 堆上没有任何指针的对象会发生啥?

切换场景时JavaFX选择框空指针异常

为啥mac不需要包含智能指针? [复制]

当删除没有虚拟析构函数的多态对象时会发生啥?