公司网站开发费用济南兴田德润o简介图片,友情链接的概念,开发一款游戏需要多少钱,品牌建设案例加粗样式TOC
智能指针是代理模式的具体应用#xff0c;它使用 RAII 技术代理了裸指针#xff0c;能够自动释放内存#xff0c; 无需程序员干预#xff0c;所以被称为“智能指针”。
智能指针不是指针#xff0c;而是一个对象#xff0c;所以不要对其调用deleteTOC
智能指针是代理模式的具体应用它使用 RAII 技术代理了裸指针能够自动释放内存 无需程序员干预所以被称为“智能指针”。
智能指针不是指针而是一个对象所以不要对其调用delete它会自动管理初始化时的指针在离开作用域时析构释放内存。
智能指针也没有定义加减运算不能随意移动指针地址这样避免了指针越界操作。
在使用上
如果指针是“独占”使用就应该选择 unique_ptr它为裸指针添加了很多限制更加安全 。
如果指针是“共享”使用就应该选择 shared_ptr它的功能非常完善用法几乎与原始指针一样
使用智能指针要加头文件#include memory
工厂函数make_unique()、make_shared()不只是返回智能指针对象其内部也有优化。
如果你已经理解了智能指针就尽量不要再使用裸指针、new 和 delete 来操作内存了。
unique_ptr
unique_ptr需要手动初始化声明的时候必须用模板参数指定类型
unique_ptrint ptr1(new int(10)); // int智能指针
assert(*ptr1 10); // 可以使用*取内容
assert(ptr1 ! nullptr); // 可以判断是否为空指针
unique_ptrstring ptr2(new string(hello)); // string智能指针
assert(*ptr2 hello); // 可以使用*取内容
assert(ptr2-size() 5); // 可以使用-调用成员函数也可以调用工厂函数强制创建智能指针的时候必须初始化
auto ptr3 make_uniqueint(42); // 工厂函数创建智能指针
assert(ptr3 *ptr3 42);
auto ptr4 make_uniquestring(god of war); // 工厂函数创建智能指针
assert(!ptr4-empty());unique_ptr表示该智能指针的所有权是唯一的不允许共享任何时候只能有一个人持有。
它禁止拷贝赋值但是可以使用std::move()显式地声明所有权转移
auto ptr1 make_uniqueint(42); // 工厂函数创建智能指针
assert(ptr1 *ptr1 42); // 此时智能指针有效
auto ptr2 ptr1; // 编译有问题
auto ptr2 std::move(ptr1); // 使用move()转移所有权
assert(ptr2 *ptr2 42);
assert(ptr1); // 此时智能指针无效.会报错指针的所有权就被转走了原来的 unique_ptr 变成了空指针新的 unique_ptr 接替了管理权保证所有权的唯一性
shared_ptr
基本使用方式与unique_ptr并无不同
shared_ptrint ptr1(new int(10)); // int智能指针
assert(*ptr1 10); // 可以使用*取内容
shared_ptrstring ptr2(new string(hello)); // string智能指针
assert(*ptr2 hello); // 可以使用*取内容
auto ptr3 make_sharedint(42); // 工厂函数创建智能指针
assert(ptr3 *ptr3 42); // 可以判断是否为空指针
auto ptr4 make_sharedstring(zelda); // 工厂函数创建智能指针
assert(!ptr4-empty()); // 可以使用-调用成员函数不过它的所有权可以被安全共享支持拷贝赋值
auto ptr1 make_sharedint(42); // 工厂函数创建智能指针
assert(ptr1 ptr1.unique() ); // 此时智能指针有效且唯一
auto ptr2 ptr1; // 直接拷贝赋值不需要使用move()
assert(ptr1 ptr2); // 此时两个智能指针均有效
assert(ptr1 ptr2); // shared_ptr可以直接比较
// 两个智能指针均不唯一且引用计数为2
assert(!ptr1.unique() ptr1.use_count() 2);
assert(!ptr2.unique() ptr2.use_count() 2);其内部使用引用计数所以具有完整的”值语义“可以在任何场合下代替原始指针。
不过维护引用计数的存储和管理都是成本过度使用会降低运行效率。其引用计数也会带来循环引用下面是简化后的典型例子
#include iostream
#include memory
#include assert.h
using namespace std;
class Node final {
public:using this_type Node;using shared_type std::shared_ptrthis_type;shared_type next; // 使用只能指针来指向下一个节点
};
int main() {auto n1 make_sharedNode(); // 工厂函数创建智能指针auto n2 make_sharedNode();// 此时引用计数均为1assert(n1.use_count() 1);assert(n2.use_count() 1);// 产生循环引用n1-next n2;n2-next n1;// 此时引用计数均为2,且无法减到0内存泄露assert(n1.use_count() 2);assert(n2.use_count() 2);
}这个例子很简单你一下子就能看出存在循环引用。但在实际开发中指针的关系可不像例 子那么清晰很有可能会不知不觉形成一个链条很长的循环引用复杂到你根本无法识别 想要找出来基本上是不可能的。 想要从根本上杜绝循环引用光靠 shared_ptr 是不行了必须要用到weak_ptr。
weak_ptr
它专门为打破循环引用而设计只观察指针不会增 加引用计数弱引用但在需要的时候可以调用成员函数 lock()获取 shared_ptr强引用 。用法如下
#include iostream
#include memory
#include assert.h
using namespace std;
class Node final {
public:using this_type Node;// 改用weak_ptrusing shared_type std::weak_ptrthis_type;shared_type next; // 使用只能指针来指向下一个节点
};
int main() {auto n1 make_sharedNode(); // 工厂函数创建智能指针auto n2 make_sharedNode();// 此时引用计数均为1assert(n1.use_count() 1);assert(n2.use_count() 1);// 产生循环引用n1-next n2;n2-next n1;// 因为使用了weak_ptr引用计数为1assert(n1.use_count() 1);assert(n2.use_count() 1);if (!n1-next.expired()) { // 检查指针是否有效auto ptr n1-next.lock(); // lock()获取shared_ptrassert(ptr n2);}
}