在c ++中,删除对象时对对象的明确引用

时间:2015-10-06 11:44:29

标签: c++

让我们说A引用B。

可以有数以百万计的B被各种不同的东西引用。

问题是:B可以被删除然后A(或任何其他对象)可以指向垃圾,如果它去使用它我们将获得AccessViolation。

我认为正常的解决方案是B需要维护一个链接,这样我们就可以使引用无效。

是否有任何类型的智能指针可以处理这种情况?例如当B被删除时,它将使对自身的引用无效?

添加示例:

class B
{
  int x;
}

class A
{
   public:
   B* DangerousPointer;
};

假设B可以随时删除,有数百万B,还有很多可以引用B的东西。我想知道B是否已被删除,因此我无法访问它并获得访问冲突。理想情况下,我不希望B必须跟踪所有引用它的A,以便A知道在删除B时将指针归零。

关于使用weak_ptr的另一个问题:

我们的软件目前根本不使用weak_ptr或shared_ptr。我们有一个smurfClass(s​​murf命名约定),它保存了一个smurfAttributes列表。

删除smurfClass后,我们还会删除所有smurfAttributes。 许多其他不同的东西可能想要引用smurfAttribute,但是当我们删除一个类及其所有属性时,我们偶尔会遇到问题,并且某些东西指向已被删除的smurfAttribute。

是否可以将weak_ptr分发给smurfAttribute?

从文档中说:

weak_ptr类模板存储一个已经由shared_ptr管理的对象的“弱引用”。

这是否意味着我不能将weak_ptr传递给smurfAttribute(因为它不是由shared_ptr管理的)?我不想让smurfAttribute保持活着,但我确实需要知道它是否已被删除,所以我不会尝试使用它。

2 个答案:

答案 0 :(得分:2)

这是std::shared_ptr的用途。当您创建shared_ptr时,只要存在一个引用,内存仍然有效。以下是使用共享指针的一个小例子:

#include <iostream>
#include <memory>

void use_shared_ptr(std::shared_ptr<int> sp)
{
    std::cout << "in use_shared_ptr() count is: " << sp.use_count() << std::endl;
}

std::shared_ptr<int> function_that_returns_a_local_object()
{
    auto foo = std::make_shared<int>(42);
    std::cout << "just created shared_ptr.  count is: " << foo.use_count() << std::endl;
    use_shared_ptr(foo);
    std::cout << "after use_shared_ptr(foo) count is " << foo.use_count() << std::endl;
    return foo;
} // oh no.  foo gets destroyed here.  what is going to happen?

int main() 
{
    auto bar = function_that_returns_a_local_object();
    std::cout << "back in main count is: " << bar.use_count() << std::endl;
}

输出:

just created shared_ptr.  count is: 1
in use_shared_ptr() count is: 2
after use_shared_ptr(foo) count is 1
back in main count is: 1

这方面的优点是没有手动内存管理,然后完全使用shared_ptr它会破坏自己清理用make_shared分配的内存

您还可以分发std::weak_ptrweak_ptr允许删除基础指针,除非您调用lock创建共享指针,该指针将延长基础指针的生命周期,直到删除shared_ptr为止。当你想给调用者一个对象时你通常会使用它,但你不想让他们保证在他们想要使用它时它仍然存在。 weak_ptr确实有办法检查基础指针是否被删除,如果对象存在,它还能够将其转换为shared_ptr,这样可以在使用时延长指针的生命周期它

编辑:

为响应smurfClass中{}}}中您的问题的添加,所有smurfAttributes都将存储为std::shared_ptr<smurfAttributes>。然后在将属性传递给其他人的函数中,您将返回std::weak_ptr。这样,属性的接收者必须尝试锁定weak_ptr以便使用它,如果不能,则它知道它不再具有有效属性。

答案 1 :(得分:0)

我认为你想要的一个例子是openCV Mat对象。 它是图像的容器。实际数据存储在堆(ucahr* data)中。

因此,当您要删除Mat对象时,数据将被删除,但垫本身仍然存在。 Mat本身可以在堆栈中创建,其中的数据将在堆中创建。

微小的未经测试的例子:

class my_container {
    my_container() {
        data = new your_class();
    }

    your_class* get_data() {
        if (data == nullptr) {
            //throw catchable exception or what ever you want
        }
        return data;
    }

    void delete() {
        delete data;
        data = nullptr;
    }
private:
    your_class* data;
}

当然,如果在销毁作为堆栈的my_container对象之前没有释放数据,这将导致内存韭菜。因此,您可以向此类添加智能指针设计模式