让我们说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(smurf命名约定),它保存了一个smurfAttributes列表。
删除smurfClass后,我们还会删除所有smurfAttributes。 许多其他不同的东西可能想要引用smurfAttribute,但是当我们删除一个类及其所有属性时,我们偶尔会遇到问题,并且某些东西指向已被删除的smurfAttribute。
是否可以将weak_ptr分发给smurfAttribute?
从文档中说:
weak_ptr类模板存储一个已经由shared_ptr管理的对象的“弱引用”。
这是否意味着我不能将weak_ptr传递给smurfAttribute(因为它不是由shared_ptr管理的)?我不想让smurfAttribute保持活着,但我确实需要知道它是否已被删除,所以我不会尝试使用它。
答案 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_ptr
。 weak_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
对象之前没有释放数据,这将导致内存韭菜。因此,您可以向此类添加智能指针设计模式