shared_ptr通过引用计数精确管理对象生命周期,强引用归零时立即销毁对象;其线程安全性体现在控制块的引用计数操作是原子的,但多线程访问同一对象仍需外部同步。

shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
每个
shared_ptr
shared_ptr
weak_ptr
当一个
shared_ptr
shared_ptr
reset()
立即学习“C++免费学习笔记(深入)”;
对象的销毁逻辑是这样的:
shared_ptr
这种机制确保了只要有任何一个
shared_ptr
delete
new
delete
然而,
shared_ptr
shared_ptr
weak_ptr
#include <iostream>
#include <memory>
#include <vector>
class MyObject {
public:
int id;
MyObject(int i) : id(i) {
std::cout << "MyObject " << id << " created." << std::endl;
}
~MyObject() {
std::cout << "MyObject " << id << " destroyed." << std::endl;
}
};
void func(std::shared_ptr<MyObject> obj) {
std::cout << "Inside func, obj " << obj->id << " use_count: " << obj.use_count() << std::endl;
} // obj离开作用域,强引用计数-1
int main() {
std::cout << "--- Start main ---" << std::endl;
{
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(1); // 强引用计数: 1
std::cout << "ptr1 created, use_count: " << ptr1.use_count() << std::endl;
std::shared_ptr<MyObject> ptr2 = ptr1; // 强引用计数: 2
std::cout << "ptr2 copied from ptr1, use_count: " << ptr1.use_count() << std::endl;
func(ptr1); // 传参会创建临时shared_ptr,强引用计数: 3 (进入func时), 2 (退出func时)
std::vector<std::shared_ptr<MyObject>> vec;
vec.push_back(ptr1); // 强引用计数: 3
std::cout << "ptr1 added to vector, use_count: " << ptr1.use_count() << std::endl;
ptr2.reset(); // ptr2重置,不再管理对象,强引用计数: 2
std::cout << "ptr2 reset, ptr1 use_count: " << ptr1.use_count() << std::endl;
} // ptr1和vec中的shared_ptr离开作用域,强引用计数最终降为0,对象被销毁
std::cout << "--- End main ---" << std::endl;
return 0;
}运行上述代码,你会清晰地看到
MyObject 1 destroyed.
--- End main ---
ptr1
vec
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
当一个
shared_ptr
std::make_shared
shared_ptr
shared_ptr
reset()
对象的实际销毁,即调用其析构函数并释放内存,发生在强引用计数降至零的那一刻。这一机制确保了:
shared_ptr
shared_ptr
这种“即时且延迟”的销毁策略,完美契合了RAII(Resource Acquisition Is Initialization)原则,将资源的生命周期与管理它们的
shared_ptr
delete
shared_ptr
#include <iostream>
#include <memory>
class Resource {
public:
Resource(int id) : id_(id) {
std::cout << "Resource " << id_ << " acquired." << std::endl;
}
~Resource() {
std::cout << "Resource " << id_ << " released." << std::endl;
}
private:
int id_;
};
void process(std::shared_ptr<Resource> res) {
std::cout << "Processing Resource " << res->id_ << ". Use count: " << res.use_count() << std::endl;
} // res离开作用域,强引用计数-1
int main() {
std::shared_ptr<Resource> r1 = std::make_shared<Resource>(101); // 强引用计数: 1
std::cout << "Main scope: r1 use count: " << r1.use_count() << std::endl;
{
std::shared_ptr<Resource> r2 = r1; // 强引用计数: 2
std::cout << "Inner scope: r1 use count: " << r1.use_count() << std::endl;
process(r2); // 传参导致临时shared_ptr,强引用计数: 3 (进入), 2 (退出)
} // r2离开作用域,强引用计数: 1
std::cout << "Main scope: r1 use count after inner scope: " << r1.use_count() << std::endl;
// r1离开作用域,强引用计数: 0,Resource 101 被销毁
return 0;
}通过观察输出,我们可以清楚地看到
Resource 101 released.
main
r1
shared_ptr
shared_ptr
weak_ptr
循环引用是
shared_ptr
shared_ptr
shared_ptr
shared_ptr
想象一下一个父子关系:一个
Parent
Child
shared_ptr
Child
Parent
shared_ptr
#include <iostream>
#include <memory>
class Child; // 前向声明
class Parent {
public:
std::shared_ptr<Child> child;
int id;
Parent(int i) : id(i) { std::cout << "Parent " << id << " created." << std::endl; }
~Parent() { std::cout << "Parent " << id << " destroyed." << std::endl; }
};
class Child {
public:
std::shared_ptr<Parent> parent; // 这里是导致循环引用的点
int id;
Child(int i) : id(i) { std::cout << "Child " << id << " created." << std::endl; }
~Child() { std::cout << "Child " << id << " destroyed." << std::endl; }
};
void create_circular_ref() {
std::shared_ptr<Parent> p = std::make_shared<Parent>(1);
std::shared_ptr<Child> c = std::make_shared<Child>(2);
p->child = c; // Parent持有Child,c的强引用计数变为2
c->parent = p; // Child持有Parent,p的强引用计数变为2
std::cout << "Parent use_count: " << p.use_count() << std::endl; // 2
std::cout << "Child use_count: " << c.use_count() << std::endl; // 2
} // p和c离开作用域,各自的强引用计数减1,但仍为1,对象不会被销毁在
create_circular_ref
p
c
Parent 1
Child 2
weak_ptr
weak_ptr
shared_ptr
weak_ptr
shared_ptr
weak_ptr
当需要访问
weak_ptr
lock()
shared_ptr
lock()
shared_ptr
shared_ptr
使用
weak_ptr
weak_ptr
#include <iostream>
#include <memory>
class Child_Fixed; // 前向声明
class Parent_Fixed {
public:
std::shared_ptr<Child_Fixed> child;
int id;
Parent_Fixed(int i) : id(i) { std::cout << "Parent_Fixed " << id << " created." << std::endl; }
~Parent_Fixed() { std::cout << "Parent_Fixed " << id << " destroyed." << std::endl; }
};
class Child_Fixed {
public:
std::weak_ptr<Parent_Fixed> parent; // 使用weak_ptr打破循环
int id;
Child_Fixed(int i) : id(i) { std::cout << "Child_Fixed " << id << " created." << std::endl; }
~Child_Fixed() { std::cout << "Child_Fixed " << id << " destroyed." << std::endl; }
void access_parent() {
if (auto p = parent.lock()) { // 尝试获取shared_ptr
std::cout << "Child_Fixed " << id << " accessing Parent_Fixed " << p->id << std::endl;
} else {
std::cout << "Child_Fixed " << id << ": Parent_Fixed no longer exists." << std::endl;
}
}
};
void create_fixed_ref() {
std::shared_ptr<Parent_Fixed> p = std::make_shared<Parent_Fixed>(1);
std::shared_ptr<Child_Fixed> c = std::make_shared<Child_Fixed>(2);
p->child = c; // Parent持有Child,c的强引用计数变为2
c->parent = p; // Child弱引用Parent,p的强引用计数仍为1
std::cout << "Parent_Fixed use_count: " << p.use_count() << std::endl; // 1
std::cout << "Child_Fixed use_count: " << c.use_count() << std::endl; // 2
c->access_parent(); // 此时Parent_Fixed仍然存在
} // p和c离开作用域,强引用计数归零,对象被销毁现在,当
create_fixed_ref
p
c->parent
weak_ptr
Parent_Fixed 1
p
p->child
shared_ptr<Child_Fixed>
c
c
Child_Fixed 2
weak_ptr
shared_ptr
shared_ptr
shared_ptr
delete
shared_ptr
new
应用场景:
std::shared_ptr<T>
delete obj;
new T[size];
delete[] obj;
FILE*
fclose()
closesocket()
sqlite3_close()
lib_malloc()
lib_free()
如何影响对象销毁: 当
shared_ptr
delete
shared_ptr
#include <iostream>
#include <memory>
#include <cstdio> // For FILE operations
// 1. 管理C风格数组
void array_deleter(int* p) {
std::cout << "Custom array deleter called for " << p << std::endl;
delete[] p;
}
// 2. 管理文件句柄
void file_closer(FILE* f) {
if (f) {
std::cout << "Custom file closer called for " << f << std::endl;
fclose(f);
}
}
int main() {
std::cout << "--- Custom Deleter Examples ---" << std::endl;
// 示例1:管理C风格数组
std::shared_ptr<int> intArray(new int[5], array_deleter);
for (int i = 0; i < 5; ++i) {
intArray.get()[i] = i * 10;
}
std::cout << "intArray use_count: " << intArray.use_count() << std::endl;
// 当intArray离开作用域时,array_deleter会被调用
// 示例2:管理文件句柄
FILE* file = fopen("test.txt", "w");
if (file) {
std::shared_ptr<FILE> filePtr(file, file_closer);
fprintf(filePtr.get(), "Hello from shared_ptr!\n");
std::cout << "filePtr use_count: " << filePtr.use_count() << std::endl;
} else {
std::cerr << "Failed to open file." << std::endl;
}
// 当filePtr离开作用域时,file_closer会被调用
// 示例3:使用Lambda表达式作为删除器 (更常见和简洁)
auto customDeleter = [](std::string* s) {
std::cout << "Lambda deleter called for string: " << *s << std::endl;
delete s;
};
std::shared_ptr<std::string> myString(new std::string("Hello Lambda"), customDeleter);
std::cout << "myString use_count: " << myString.use_count() << std::endl;
std::cout << "--- End Custom Deleter Examples ---" << std::endl;
return 0;
}在我看来,自定义删除器是
shared_ptr
shared_ptr
close()
free()
shared_ptr
以上就是C++shared_ptr对象销毁顺序与内存管理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号