赞
踩
目录
C++中的智能指针是用来管理动态内存的对象,避免我们手动管理内存时可能会带来的复杂性和错误。C++标准库提供了几种不同类型的智能指针,包括`std::unique_ptr`、`std::shared_ptr`和`std::weak_ptr`。
1. `std::unique_ptr`是独占所有权的智能指针,即同一时间只能有一个`std::unique_ptr`指向特定的对象。
2. 当`std::unique_ptr`被销毁时,它所管理的对象会被自动释放。
3. 不能复制`std::unique_ptr`,只能移动它。
4. 当`std::unique_ptr`超出作用域时,它会自动释放资源。
5. 避免从原始指针创建多个`std::unique_ptr`,这会导致双重释放问题。
- #include <iostream>
- #include <memory>
-
- class MyClass {
- public:
- MyClass() {
- std::cout << "MyClass Constructor" << std::endl;
- }
- ~MyClass() {
- std::cout << "MyClass Destructor" << std::endl;
- }
- void show() {
- std::cout << "MyClass show" << std::endl;
- }
- };
-
- void uniquePtrExample() {
- std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
- ptr->show();
-
- // 移动所有权
- std::unique_ptr<MyClass> ptr2 = std::move(ptr);
- if (!ptr) {
- std::cout << "ptr is null after move" << std::endl;
- }
- ptr2->show();
- }
-
- int main() {
- uniquePtrExample();
- return 0;
- }
1. `std::shared_ptr`是共享所有权的智能指针,即可以有多个`std::shared_ptr`指向同一个对象。
2. 当最后一个`std::shared_ptr`被销毁时,对象会被自动释放。
3. `std::shared_ptr`使用引用计数来管理对象,当引用计数为零时,释放对象。
4. 避免循环引用(Circular Reference),这会导致内存泄漏。使用`std::weak_ptr`解决这个问题。
5. 使用`std::make_shared`创建`std::shared_ptr`,这可以减少内存分配的次数并提高性能。
- #include <iostream>
- #include <memory>
-
- class MyClass {
- public:
- MyClass() {
- std::cout << "MyClass Constructor" << std::endl;
- }
- ~MyClass() {
- std::cout << "MyClass Destructor" << std::endl;
- }
- void show() {
- std::cout << "MyClass show" << std::endl;
- }
- };
-
- void sharedPtrExample() {
- std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
- {
- std::shared_ptr<MyClass> ptr2 = ptr1;
- ptr2->show();
- std::cout << "Reference count: " << ptr1.use_count() << std::endl;
- }
- std::cout << "Reference count after scope: " << ptr1.use_count() << std::endl;
- }
-
- int main() {
- sharedPtrExample();
- return 0;
- }
1. `std::weak_ptr`是一个不拥有所有权的智能指针,它用于监视`std::shared_ptr`的生命周期。
2. `std::weak_ptr`不会影响`std::shared_ptr`的引用计数,主要用于避免循环引用。
3. `std::weak_ptr`不能直接访问对象,需要通过`lock`方法获取`std::shared_ptr`来访问对象。
4. `std::weak_ptr`用于打破`std::shared_ptr`的循环引用。
- #include <iostream>
- #include <memory>
-
- class MyClass {
- public:
- MyClass() {
- std::cout << "MyClass Constructor" << std::endl;
- }
- ~MyClass() {
- std::cout << "MyClass Destructor" << std::endl;
- }
- void show() {
- std::cout << "MyClass show" << std::endl;
- }
- };
-
- void weakPtrExample() {
- std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
- std::weak_ptr<MyClass> weakPtr = ptr1;
-
- if (auto sharedPtr = weakPtr.lock()) {
- sharedPtr->show();
- std::cout << "Reference count: " << sharedPtr.use_count() << std::endl;
- } else {
- std::cout << "The managed object has been deleted." << std::endl;
- }
- }
-
- int main() {
- weakPtrExample();
- return 0;
- }
`std::make_unique`和`std::make_shared`分别是C++14和C++11时期引入的工厂函数,用于创建智能指针对象。提供了一种安全、高效的方式来分配内存并初始化智能指针,从而减少我们手动使用`new`带来的错误风险。
`std::make_unique`用于创建一个`std::unique_ptr`实例。
1. 防止内存泄漏:
使用`std::make_unique`可以防止在内存分配和对象构造之间发生异常时的内存泄漏问题。
2. 安全方面:
相比手动使用`new`,`std::make_unique`更加安全,不会产生裸指针。
- #include <iostream>
- #include <memory>
-
- class MyClass {
- public:
- MyClass(int x) : value(x) {
- std::cout << "MyClass Constructor, value: " << value << std::endl;
- }
- ~MyClass() {
- std::cout << "MyClass Destructor" << std::endl;
- }
- void show() {
- std::cout << "Value: " << value << std::endl;
- }
- private:
- int value;
- };
-
- void uniquePtrExample() {
- std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>(42);
- ptr->show();
- }
-
- int main() {
- uniquePtrExample();
- return 0;
- }
`std::make_shared`用于创建一个`std::shared_ptr`实例。
1. 单次内存分配:
`std::make_shared`通过一次内存分配同时创建控制块和对象,从而减少了内存分配的次数,提升了性能。
2. 防止内存泄漏:
使用`std::make_shared`可以防止在内存分配和对象构造之间发生异常时的内存泄漏问题。
3. 简洁和安全:
相比手动使用`new`,`std::make_shared`更加简洁且安全,不会产生裸指针。
- #include <iostream>
- #include <memory>
-
- class MyClass {
- public:
- MyClass(int x) : value(x) {
- std::cout << "MyClass Constructor, value: " << value << std::endl;
- }
- ~MyClass() {
- std::cout << "MyClass Destructor" << std::endl;
- }
- void show() {
- std::cout << "Value: " << value << std::endl;
- }
- private:
- int value;
- };
-
- void sharedPtrExample() {
- std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>(42);
- ptr->show();
- }
-
- int main() {
- sharedPtrExample();
- return 0;
- }
`std::make_shared`通过一次内存分配同时创建控制块和对象,提升了性能,但如果不需要共享所有权,可以优先选择`std::make_unique`。
我们使用`std::make_shared`创建了树状结构的节点,并使用智能指针来管理节点的生命周期。通过`std::make_shared`,我们确保了节点在超出作用域时会自动释放内存,避免了内存泄漏。
- #include <iostream>
- #include <memory>
- #include <vector>
-
- class Node {
- public:
- Node(int value) : value(value) {
- std::cout << "Node Constructor, value: " << value << std::endl;
- }
- ~Node() {
- std::cout << "Node Destructor, value: " << value << std::endl;
- }
- void addChild(std::shared_ptr<Node> child) {
- children.push_back(child);
- }
- void show() const {
- std::cout << "Node value: " << value << ", children: ";
- for (const auto& child : children) {
- std::cout << child->value << " ";
- }
- std::cout << std::endl;
- }
- private:
- int value;
- std::vector<std::shared_ptr<Node>> children;
- };
-
- void treeExample() {
- auto root = std::make_shared<Node>(1);
- auto child1 = std::make_shared<Node>(2);
- auto child2 = std::make_shared<Node>(3);
-
- root->addChild(child1);
- root->addChild(child2);
-
- root->show();
- child1->show();
- child2->show();
- }
-
- int main() {
- treeExample();
- return 0;
- }
1. 使用`std::make_unique`和`std::make_shared`:
优先使用`std::make_unique`和`std::make_shared`来创建智能指针,避免手动使用`new`,可以提高代码的安全性和性能。
2. 避免循环引用:
在使用`std::shared_ptr`时要特别小心循环引用的问题。可以使用`std::weak_ptr`来打破循环引用。
3. 注意生命周期:
确保智能指针的生命周期管理正确,避免悬空指针和内存泄漏。
4. 考虑性能:
虽然智能指针极大地简化了内存管理,但也带来了额外的开销,如引用计数的维护。因此,在性能敏感的代码中,应慎重使用`std::shared_ptr`。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。