在开始之前,先定义一个为了测试用的MyObject
类。
class MyObject
{
private:
int m_Value = 0;
int m_Data[10240]; // 这一坨是为了占空间
std::shared_ptr<MyObject> m_Child;
public:
MyObject(const int value)
{
m_Value = value;
}
int GetValue()
{
return m_Value;
}
void SetChild(std::shared_ptr<MyObject>& child)
{
m_Child = child;
}
};
unique_ptr
unique_ptr只允许同一块堆内存被一个unique_ptr持有。代码上看起来是这样的。
std::unique_ptr<MyObject> up_obj(new MyObject(100));
//std::unique_ptr<MyObject> up_obj2(up_obj); // 报错 C2280
//std::unique_ptr<MyObject> up_obj3;
//up_obj3 = up_obj; // 报错 C2280
std::shared_ptr<MyObject> sp_obj(new MyObject(200));
// 将一个unique_ptr赋值给其它智能指针也是不行的
//std::shared_ptr<MyObject> sp_o = up_obj; // C2440
//std::unique_ptr<MyObject> up_fuck = sp_obj; // C2440
// 这样是可以编译通过的,但是运行时会出错
std::shared_ptr<MyObject> sppp(up_obj.get());
shared_ptr
这个类型的智能指针用起来的风格,就非常像Java了。
std::shared_ptr<MyObject> sp_obj(new MyObject(123));
std::shared_ptr<MyObject> sp_obj2(sp_obj);
std::shared_ptr<MyObject> sp_obj3 = sp_obj;
std::cout << "sp_obj value: " << sp_obj->GetValue() << " use count: " << sp_obj.use_count() << std::endl;
运行后内存中应该是这个样子的。
shared_ptr是通过引用计数的方式来实现的,也就是说,它解决不了循环引用。
实验如下:
先写一个方法,里面构造了两个shared_ptr,因为MyObject对象里面有个shared_ptr成员变量,因此让这两个对象相互引用。
void testLoopRef()
{
std::shared_ptr<MyObject> sp_obj111(new MyObject(111));
std::shared_ptr<MyObject> sp_obj999(new MyObject(999));
sp_obj111->SetChild(sp_obj999);
sp_obj999->SetChild(sp_obj111);
}
然后再将这个方法放到主函数中运行,端点执行,查看每一步的内存变化。
内存中看起来应该是这个样子:
weak_ptr
为了解决循环引用的问题,可以使用weak_ptr来搞。
我们将MyObject
类,进行改造,把它的m_Child属性改成weak_ptr的。
class MyObject2
{
private:
int m_Value = 0;
int m_Data[10240];
std::weak_ptr<MyObject2> m_Child;
public:
MyObject2(const int value)
{
m_Value = value;
}
int GetValue()
{
return m_Value;
}
void SetChild(std::shared_ptr<MyObject2>& child)
{
m_Child = child;
}
};
然后,再次使用和上面代码几乎一样的代码进行测试。
总结
这里只是一个初步的,浅显的关于“用法”的学习探究过程的记录。因为还没有投入到实战中用过,所以也没有什么特别的心得体会和技巧分享给大家。
参考
智能指针(现代 C++)
如何:创建和使用 unique_ptr 实例
如何:创建和使用 shared_ptr 实例
如何:创建和使用共享 weak_ptr 实例
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。