C++智能指针与内存管理实践
C++智能指针与内存管理实践
智能指针是C++中自动管理动态内存的关键工具。通过RAII机制,智能指针在对象生命周期结束时自动释放内存,避免内存泄漏和悬空指针问题。
std::unique_ptr提供独占所有权语义,确保同一时刻只有一个指针拥有资源。它的开销极小,几乎等同于原始指针。
#include
#include
#include
class Resource {
int id_;
std::vector data_;
public:
explicit Resource(int id) : id_(id), data_(1000, id) {
std::cout << "Resource " << id_ << " created\n";
}
~Resource() {
std::cout << "Resource " << id_ << " destroyed\n";
}
void process() {
std::cout << "Processing resource " << id_ << "\n";
}
int id() const { return id_; }
};
void unique_ptr_basic() {
std::unique_ptr ptr1(new Resource(1));
ptr1->process();
auto ptr2 = std::make_unique(2);
ptr2->process();
std::unique_ptr ptr3 = std::move(ptr2);
if (!ptr2) {
std::cout << "ptr2 is now null\n";
}
ptr3->process();
}
std::unique_ptr的自定义删除器允许管理非内存资源,如文件句柄、网络连接等。
struct FileDeleter {
void operator()(FILE* fp) const {
if (fp) {
std::cout << "Closing file\n";
fclose(fp);
}
}
};
void custom_deleter_example() {
std::unique_ptr file(fopen("test.txt", "w"));
if (file) {
fprintf(file.get(), "Hello from unique_ptr\n");
}
}
template
class UniquePtr {
T* ptr_;
void cleanup() {
delete ptr_;
ptr_ = nullptr;
}
public:
explicit UniquePtr(T* p = nullptr) : ptr_(p) {}
~UniquePtr() {
cleanup();
}
UniquePtr(const UniquePtr&) = delete;
UniquePtr& operator=(const UniquePtr&) = delete;
UniquePtr(UniquePtr&& other) noexcept : ptr_(other.ptr_) {
other.ptr_ = nullptr;
}
UniquePtr& operator=(UniquePtr&& other) noexcept {
if (this != &other) {
cleanup();
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
return *this;
}
T* get() const { return ptr_; }
T* release() {
T* temp = ptr_;
ptr_ = nullptr;
return temp;
}
void reset(T* p = nullptr) {
cleanup();
ptr_ = p;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
};
std::shared_ptr实现引用计数,允许多个指针共享同一资源。当最后一个shared_ptr被销毁时,资源才会被释放。
void shared_ptr_basic() {
std::shared_ptr sp1 = std::make_shared(10);
std::cout << "Use count: " << sp1.use_count() << "\n";
{
std::shared_ptr sp2 = sp1;
std::cout << "Use count: " << sp1.use_count() << "\n";
sp2->process();
}
std::cout << "Use count after scope: " << sp1.use_count() << "\n";
}
template
class SharedPtr {
T* ptr_;
size_t* ref_count_;
void release() {
if (ref_count_) {
--(*ref_count_);
if (*ref_count_ == 0) {
delete ptr_;
delete ref_count_;
}
}
}
public:
explicit SharedPtr(T* p = nullptr)
: ptr_(p), ref_count_(p ? new size_t(1) : nullptr) {}
~SharedPtr() {
release();
}
SharedPtr(const SharedPtr& other)
: ptr_(other.ptr_), ref_count_(other.ref_count_) {
if (ref_count_) {
++(*ref_count_);
}
}
SharedPtr& operator=(const SharedPtr& other) {
if (this != &other) {
release();
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
if (ref_count_) {
++(*ref_count_);
}
}
return *this;
}
SharedPtr(SharedPtr&& other) noexcept
: ptr_(other.ptr_), ref_count_(other.ref_count_) {
other.ptr_ = nullptr;
other.ref_count_ = nullptr;
}
SharedPtr& operator=(SharedPtr&& other) noexcept {
if (this != &other) {
release();
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
other.ptr_ = nullptr;
other.ref_count_ = nullptr;
}
return *this;
}
T* get() const { return ptr_; }
size_t use_count() const { return ref_count_ ? *ref_count_ : 0; }
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
};
std::weak_ptr用于打破循环引用,它不增加引用计数,但可以检测对象是否仍然存在。
class Node {
public:
int value;
std::shared_ptr next;
std::weak_ptr prev;
explicit Node(int v) : value(v) {
std::cout << "Node " << value << " created\n";
}
~Node() {
std::cout << "Node " << value << " destroyed\n";
}
};
void weak_ptr_example() {
auto node1 = std::make_shared(1);
auto node2 = std::make_shared(2);
node1->next = node2;
node2->prev = node1;
if (auto prev = node2->prev.lock()) {
std::cout << "Previous node value: " << prev->value << "\n";
}
}
智能指针与容器结合使用时,可以实现多态容器和资源管理。
class Shape {
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
virtual double area() const = 0;
};
class Circle : public Shape {
double radius_;
public:
explicit Circle(double r) : radius_(r) {}
void draw() const override {
std::cout << "Drawing circle with radius " << radius_ << "\n";
}
double area() const override {
return 3.14159 * radius_ * radius_;
}
};
class Rectangle : public Shape {
double width_, height_;
public:
Rectangle(double w, double h) : width_(w), height_(h) {}
void draw() const override {
std::cout << "Drawing rectangle " << width_ << "x" << height_ << "\n";
}
double area() const override {
return width_ * height_;
}
};
void polymorphic_container() {
std::vector> shapes;
shapes.push_back(std::make_unique(5.0));
shapes.push_back(std::make_unique(4.0, 6.0));
shapes.push_back(std::make_unique(3.0));
double total_area = 0;
for (const auto& shape : shapes) {
shape->draw();
total_area += shape->area();
}
std::cout << "Total area: " << total_area << "\n";
}
make_shared相比直接使用shared_ptr构造函数更高效,因为它只进行一次内存分配。
template
std::shared_ptr make_shared_impl(Args&&... args) {
return std::shared_ptr(new T(std::forward(args)...));
}
void allocation_comparison() {
auto sp1 = std::shared_ptr(new Resource(1));
auto sp2 = std::make_shared(2);
}
智能指针的线程安全性需要特别注意。引用计数的修改是线程安全的,但对象本身的访问不是。
#include
#include
class ThreadSafeCounter {
mutable std::mutex mutex_;
int value_;
public:
ThreadSafeCounter() : value_(0) {}
void increment() {
std::lock_guard lock(mutex_);
++value_;
}
int get() const {
std::lock_guard lock(mutex_);
return value_;
}
};
void thread_safety_example() {
auto counter = std::make_shared();
std::vector threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back([counter]() {
for (int j = 0; j < 1000; ++j) {
counter->increment();
}
});
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final count: " << counter->get() << "\n";
}
enable_shared_from_this允许对象从自身获取shared_ptr,这在回调和异步操作中很有用。
class AsyncOperation : public std::enable_shared_from_this {
int id_;
public:
explicit AsyncOperation(int id) : id_(id) {}
void start() {
std::cout << "Starting operation " << id_ << "\n";
auto self = shared_from_this();
std::thread([self]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Operation " << self->id_ << " completed\n";
}).detach();
}
};
void enable_shared_from_this_example() {
auto op = std::make_shared(1);
op->start();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
智能指针的性能开销主要来自引用计数的原子操作。在性能关键路径上,unique_ptr是更好的选择。
#include
void performance_comparison() {
const int iterations = 1000000;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
auto ptr = std::make_unique(i);
volatile int value = *ptr;
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(end - start);
std::cout << "unique_ptr: " << duration.count() << " us\n";
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
auto ptr = std::make_shared(i);
volatile int value = *ptr;
}
end = std::chrono::high_resolution_clock::now();
duration = std::chrono::duration_cast(end - start);
std::cout << "shared_ptr: " << duration.count() << " us\n";
}
智能指针与异常安全紧密相关,确保即使在异常发生时资源也能正确释放。
void exception_safety() {
std::vector> resources;
try {
resources.push_back(std::make_unique(1));
resources.push_back(std::make_unique(2));
throw std::runtime_error("Error occurred");
resources.push_back(std::make_unique(3));
} catch (const std::exception& e) {
std::cout << "Exception: " << e.what() << "\n";
std::cout << "Resources automatically cleaned up\n";
}
}
智能指针是现代C++内存管理的基石。正确使用智能指针可以消除大部分内存管理问题,使代码更加安全和易于维护。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)