当智能指针过期时,其析构函数将使用delete来释放内存,因此如果将new返回的地址给这些对象,将无需记住稍后释放这些内存
包含头文件 <memory>
所有智能指针都有一个explicit的构造函数
#include <bits/stdc++.h>
#include <initializer_list>
#include <memory>
#include <vector>
using namespace std;
class Test {
public:
Test(initializer_list<int> p) {
for (auto &it:p) {
v.push_back(it);
}
}
vector<int> v;
~Test() {
cout << "Deconstructed" << endl;
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
shared_ptr<Test> p(new Test(
{1, 2, 3, 4, 5}
));
for (auto &it : p->v) {
cout << it << ',';
}
return 0;
}
auto_ptr
在[[C++]]11中已经被弃用
std::auto_ptr
实现了所有权转移的语义,即当 std::auto_ptr
被复制或赋值时,所有权会从一个对象转移到另一个对象。这意味着源对象在复制或赋值操作之后不再拥有对象的所有权,并且会变为空(null)
std::auto_ptr<int> p1(new int(10));
std::auto_ptr<int> p2 = p1; // p1 被复制到 p2,p1 不再拥有对象的所有权
// 现在 p1 为空,只有 p2 拥有对象的所有权
shared_ptr
std::shared_ptr
提供了共享所有权语义,允许多个智能指针共享同一个对象的所有权,并使用引用计数来管理对象的生命周期
unique_ptr
std::unique_ptr
提供了独占所有权语义,并且禁止复制操作,从而避免了 std::auto_ptr
的所有权转移问题。
不能被复制,但可以通过std::move
转移所有权。
(但是存在特例!如果源unique_ptr是一个临时的右值,编译器允许复制)
#include <iostream>
#include <memory>
std::unique_ptr<int> createUniquePtr() {
return std::make_unique<int>(10); // 返回一个临时的unique_ptr
}
int main() {
std::unique_ptr<int> p1 = createUniquePtr(); // 移动构造,允许从临时右值移动
std::cout << *p1 << std::endl; // 输出 10
std::unique_ptr<int> p2 = std::make_unique<int>(20);
// std::unique_ptr<int> p3 = p2; // 错误,不能复制
std::unique_ptr<int> p4 = std::move(p2); // 移动构造,允许从左值移动
std::cout << *p4 << std::endl; // 输出 20
return 0;
}
make_unique 与 new 比较
std::make_unique
可以防止由于new
操作符可能引发的内存泄漏问题
std::make_unique
提供了强异常安全性。如果在构造过程中抛出异常,它能够确保没有内存泄漏,因为内存分配和构造是一个原子操作。
相对来说,new的异常安全性较差:
- 在复杂表达式中,如果
new
操作符成功分配内存,但在构造std::unique_ptr
对象之前抛出异常,可能会导致内存泄漏