动态内存
new
placement new
是 C++ 中的一种内存分配方式,它允许在给定的内存地址上构造对象,而不是在默认的堆上分配新的内存。这对于某些特殊的内存管理场景非常有用,例如在特定的内存池中分配对象。
C++11 引入了 "new auto" 语法,它允许你使用 auto
关键字来推断要分配的对象的类型。使用 "new auto" 的语法可以简化代码,特别是在创建复杂的类型或者使用模板时。
// 使用 new auto 分配整数
auto* myInt = new auto(42);
// 使用 new auto 分配浮点数
auto* myDouble = new auto(3.14);
alignas
是 C++11 引入的一个关键字,用于指定对齐方式。它可以用于变量、类型、结构体、类等,使得相应的对象或结构体成员按照指定的对齐方式进行对齐。
new会考虑struct的对齐信息
delete
不要delete非new返回的内存
智能指针
所有权不清晰 没销毁
解决方法:
share_ptr
常用接口
1. get
函数:
get
函数用于获取指向所管理对象的原始指针。这个原始指针可以用于调用不接受智能指针的函数或与 C 接口进行交互。需要注意的是,get
函数返回的是一个裸指针,它不负责引用计数,也不会影响 std::shared_ptr
的所有权。
-
- unique函数:判断该shared_ptr对象是否独占若独占,返回true。否则返回false。
-
- reset函数:
- 当reset函数有参数时,改变此shared_ptr对象指向的内存。
- 当reset函数无参数时,将此shared_ptr对象置空,也就是将对象内存的指针设置为nullptr。
- reset函数:
指定内存回收逻辑
C++17和20支持的数组
new数组和delete不匹配现象
C++17和20解决方法
#include<iostream>
#include<memory>
int main(){
std::shared_ptr<int>x(new int[5]);
//delete(x.get())
//C++17做法
std::shared_ptr<int[]>x2(new int[5]);
//C++20做法
auto x3=std::shared_ptr<int[5]>();
return 0;
}
unique_ptr
常用函数
-
- unque_ptr禁止复制构造函数,也禁止赋值运算符的重载。否则独占便毫无意义。、
-
- unqiue_ptr允许移动构造,移动赋值。移动语义代表之前的对象已经失去了意义,移动操作自然不影响独占的特性。
-
- reset函数:
- 不带参数的情况下:释放智能指针的对象,并将智能指针置空。
- 带参数的情况下:释放智能指针的对象,并将智能指针指向新的对象。
- reset函数:
unique_ptr要传入del
weak_ptr和循环引用
x,y形成环 循环引用
智能指针实现原理
析构两次的解决方法
auto_ptr:管理权转移
template<class T>
class auto_ptr {
public:
auto_ptr(T* ptr) :_ptr(ptr) {}
auto_ptr(auto_ptr<T>& ap) :_ptr(ap._ptr) {
ap._ptr = nullptr;
}
~auto_ptr()
{
if (_ptr) {
cout << "delete:" << _ptr << endl;
delete _ptr;
_ptr = nullptr;
}
}
T& operator*() {
return *_ptr;
}
T* operator->() {
return _ptr;
}
private:
T* _ptr;
};
缺陷:auto_ptr的问题:当对象拷贝或者赋值后,前面的对象就悬空了
C++98中设计的auto_ptr问题是非常明显的,所以实际中很多公司明确规定了不能使用auto_ptr
unique_ptr:防拷贝
template<class T>
class unique_ptr {
public:
unique_ptr(T* ptr) :_ptr(ptr) {}
unique_ptr(unique_ptr<T>& ap) :_ptr(ap._ptr) {
ap._ptr = nullptr;
}
unique_ptr<T>& operator=(unique_ptr<T>& up) = delete;
~unique_ptr()
{
if (_ptr) {
cout << "delete:" << _ptr << endl;
delete _ptr;
_ptr = nullptr;
}
}
T& operator*() {
return *_ptr;
}
T* operator->() {
return _ptr;
}
private:
T* _ptr;
};
shared_ptr:引用计数
shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。
1. shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
2. 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。
3. 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
4. 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。
template<class T>
class shared_ptr {
public:
shared_ptr(T* ptr) :_ptr(ptr),_pcount(new int(1)) {}
shared_ptr(shared_ptr<T>& sp) :_ptr(sp._ptr),_pcount(sp._pcount)
{
++(*_pcount);
}
shared_ptr<T>& operator=(shared_ptr<T>& sp) {
if (this != &sp) {
if (--(*_pcount) == 0) {
delete _pcount;
delete _ptr;
}
_ptr = sp._ptr;
_pcount = sp._pcount;
++(*_pcount);
}
return *this;
}
~shared_ptr()
{
if (--(*_pcount)==0&&_ptr) {
cout << "delete:" << _ptr << endl;
delete _ptr;
_ptr = nullptr;
}
}
T& operator*() {
return *_ptr;
}
T* operator->() {
return _ptr;
}
private:
T* _ptr;
int *_pcount;
};