i am stu
//cin scanf输入数据会将空格后面刷掉
cin.getline() //获取到一行
获取资源即初始化,使用局部对象来管理资源的技术称为资源获取即初始化。
资源:操作系统中有限的东西如内存,网络套接字,互斥量,文件句柄
局部对象:存储在栈的对象,生命周期有操作系统管理
如何让资源自动销毁:使用RAII,利用c++语言局部对象自动销毁的特性来控制资源的生命周期
堆上空间进行自动化管理 – 利用对象自动析构的机制
int* p = new int(10); //裸指针
p生成临时auto_ptr对象 — 隐式构造
使用临时对象拷贝构造a_p
析构临时对象
1.难以区分指向的是单个对象还是一个数组;
2使用完指针之后无法判断是否应该销毁指针,因为无法判断指针是否“拥有”指向的对象;
3.在已经确定需要销毁指针的情况下,也无法确定是用delete关键字删除,还是有其他特殊的销毁机制,例如通过将指针传入某个特定的销毁函数来销毁指针;
4.即便已经确定了销毁指针的方法,由于1的原因,仍然无法确定到底是用delete(销毁单个对象)还是delete[(销毁一个数组);
5.假设上述的问题都解决了,也很难保证在代码的所有路径中(分支结构,异常导致的跳转),**有且仅有一次销毁指针操作;**任何一条路径遗漏都可能导致内存泄露,而销毁多次则会导致未定义行为;
6.理论上没有方法来分辨一个指针是否处于悬挂状态;
int *p = new int(0);
auto_ptr<int> ap(p);
auto_ptr<int> bp(p);//X 不能指向同一个对象
- ~Mauto_ptr()
{
delete _ptr; //对于数组也是直接delete
}
// 在析构时 他针对所有的参数类型都是直接进行delete,像数组需要delete[]_ptr;他也是直接delete掉 是他被淘汰的原因之一- 它的release()和reset()都将当前指针置为空,无意义
template<class _Ty>
class MyDeletor //完全泛化的删除器
{
public:
//MyDeletor() = default;
MyDeletor() {}
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete ptr;
}
}
};
template<class _Ty> 部分特化的删除器
class MyDeletor<_Ty[]>
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete[]ptr;
}
}
};
注意:一定要避免auto_ptr作为函数参数按值传递, 在函数调用时 函数的作用域会产生一个局部对象来接收传入的auto_ptr(拷贝构造),传入的实参就是去对原有对象的所有权,而该对象会在函数退出时被局部auto_ptr删除
int *p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2 = ap1;
cout<<*ap1;//X ap1已经失去对q指针的所有权
值语义(value semantics):所有内置类型都具有值语义
什么样的类没有值语义?(none-value-semantics type,NVST)
1.有virtual function的类
2.包含NVST成员的类
3.NVST的衍生类
4.定义自己的=operator的类
5.继承virtual基类的衍生类
c11中使用unique_ptr替代auto_ptr
将一个new操作符返回的指针传递给unique_ptr的构造函数
unique_ptr<int> pInt(new int(5));
cout<<*pInt;
可以用过std::move()函数转移指针的所有权
unique_ptr<int> pInt(new int(5));
unique_ptr<int> pInt2 = std::move(pInt);//转移所有权
cout<<*pInt;//错误
cout<<*pInt2;//正确
unique_ptr<int> pInt3(std::move(pInt2));
unique_ptr<int> func( int x)
{
unique_ptr<int> pInt(new int(x)) ;
return pInt; //返回unique_ptr5.
}
int main( )
{
int a = 5;
unique_ptr<int> ret = func(a);
cout <<*ret << endl;
}
//函数结束后,自动释放资源
int main( ) {
vector<unique_ptr<int> > vec;
unique_ptr<int> pInt(new int(5));
vec.push_back(std : :move(pInt)); //使用移动语义
}
int main()
{
unique_ptr<int[ ]> p(new int[5] {1,2,3,4,5});
p[0] = 0; //重载了operator[]
}
// class unique_ptr
template<class _Ty,class _Dx = MyDeletor<_Ty> >
class my_unique_ptr
{
public:
// old
//typedef _Ty* pointer;
//typedef _Ty element_type;
//typedef _Dx delete_type; 删除器
// c11 new
using pointer = _Ty*; //typedef _Ty* pointer;
using element_type = _Ty; //typedef _Ty element_type;
using delete_type = _Dx; //typedef _Dx delete_type;
private:
_Ty* _Ptr;
_Dx _myDeletor;//空的 占位符 占1字节 对其方式就站4字节
public:
my_unique_ptr(const my_unique_ptr&) = delete;
my_unique_ptr& operator=(const my_unique_ptr&) = delete;
my_unique_ptr(pointer _P = nullptr) :_Ptr(_P) { cout << "my_unique_ptr: " << this << endl; }
~my_unique_ptr()
{
if (_Ptr != nullptr)
{
_myDeletor(_Ptr);
_Ptr = nullptr;
}
cout << "~my_unique_ptr: " << this << endl;
}
my_unique_ptr(my_unique_ptr&& _Y)
{ //移动构造
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;
cout << " move copy my_unique_ptr : " << this << endl;
}
template<class _Uy>
my_unique_ptr& operator=(_Uy* _p )
{ //移动赋值
if (this->_Ptr ==(_Ty*) _p) return *this;
if (_Ptr != nullptr) { _myDeletor(_Ptr); }
_Ptr = _p;
return *this;
}
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
if (this == &_Y) return *this;
reset(_Y.release());
//if (_Ptr != nullptr) { _myDeletor(_Ptr); }
//_Ptr = _Y._Ptr;
//_Y._Ptr = nullptr;
cout << " move opertor=: " << endl;
return *this;
}
_Dx & get_deleter()
{
return _myDeletor;
}
const _Dx& get_deleter() const
{
return _myDeletor;
}
_Ty& operator*() const //重载*
{
return *_Ptr;
}
pointer operator->() const
{
return &**this;// _Ptr;
}
pointer get() const
{
return _Ptr;
}
operator bool() const //强转
{
return _Ptr != nullptr;
}
pointer release() //释放
{
_Ty* old = _Ptr;
_Ptr = nullptr;
return old;
}
void reset(pointer _P = nullptr)
{
pointer old = _Ptr;
_Ptr = _P;
if (old != nullptr)
{
_myDeletor(old);
}
}
void swap(my_unique_ptr _Y)
{
std::swap(_Ptr, _Y._Ptr);
std::swap(_myDeletor, _Y._myDeletor);
}
};
class Object {
private:
int value;
public:
Object(int x = 0)
:value(x)
{
cout << "create Object" << endl;
}
~Object() { cout << "destory Object" << endl; }
int& Value() { return value; }
const int& Value()const { return value; }
};
int main()
{
shared_ptr<Object> obj(new Object(100));
cout << (*obj).Value() << endl;
cout << "obj引用计数" << obj.use_count() << endl;
shared_ptr<Object> obj2 = obj;
cout << "obj引用计数" << obj.use_count() << endl;
cout << "obj2引用计数" << obj2.use_count() << endl;
//1 2 2
return 0;
}
两种方法
Object ptr = new Object(10);
std:shared_ptr<Object> pObj(ptr);//分配内存给shared_ptr 的计数器
std:.shared_ptr< Object> pObj(new Object(10));
优点 | 缺点 |
---|---|
减少单词内存分配的次数,可以增大cache局部性 | 有可能被管理的对象已经被析构了,但是他的空间还在,内存没有归还,他仍在等在weak_ptr都被清除之后才和计数器的空间一起被归还 |
两个函数用来检查共享的引用计数值
1.unique():测试该shared_ptr是否是原始指针唯一拥有者,use_count() = 1时返回TRUE;否则false
2.use_count()返回当前指针的引用计数值,效率低,只用来测试或调试
1.引用计数本身是线程安全(引用计数是原子操作)
2.多个线程同时读同一个shared_ptr对象时线程安全的
3.多个线程同时对同一个shared_ptr对象进行读和写,则需要加锁
需要用一个shared_ptr实例来初始化weak_ptr
int main()
{
shared_ptr<int> sp(new int(5));
cout << "创建前sp的引用计数:" << sp.use_count() << endl; // use_count = 1
weak_ptr<int> wp(sp);
cout << "创建后sp的引用计数:" << sp.use_count() << endl; // use_count = 1
return 0;
}
class Object
{
private:
int value;
public:
Object(int x = 0) :value(x) { cout << "creat Object" << endl; }
~Object() { cout << "deatory Object" << endl; }
int GetValue() {
return value;
}
};
int main()
{
shared_ptr<Object> sp(new Object(5));//动态开辟 用5初始化
weak_ptr<Object> wp(sp); //用shared_ptr实例初始化weak_ptr
if (shared_ptr<Object> pa = wp.lock())
{
cout << pa->GetValue() << endl;
}
else
{
cout << wp.expired() << endl;
cout << "wp所指对象为空" << endl;
}
return 0;
}
不能直接通过weak_ptr直接访问对象,可以通过lock()获得shared_ptr,进而访问原始对象
shared_ptr< T > | 有一个引用计数器,表示T的对象是否不再使用 |
scoped_ptr< T > | 当离开作用域能够自动释放的指针,不传递所有权 |
intrusive_ptr< T > | 提供自己的指针使用引用计数机制 |
shared_array< T > | 用来处理数组 |
scoped_array< T > | 用类处理数组的 |