栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

214-共享型智能指针(shared

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

214-共享型智能指针(shared

1.主函数中的两行代码都可以创建Object类型实例

class Object
{
private:
    int value;
public:
    Object(int x = 0) :value(x)
    {
        cout << "Object" << endl;
    }
    ~Object()
    {
        cout << "~Object" << endl;
    }
};

int main()
{
    std::shared_ptr op1(new Object(10));
    std::shared_ptr op2 = std::make_shared(20);
}
 

但是它们是有区别的,这两种方式的构建活动是不一样的

对于第一种方式来说,op1有一个ptr指针和一个删除器(mDeletor),ptr指针指向引用计数对象(RefCnt),引用计数对象有mptr指针和引用计数(ref),mptr直指向Object对象,Object对象的value域的值为10,在这个过程中在堆区的构建new了两次

对于第二种方式来说进行了一些的优化,它能够计算出Object的大小和引用计数对象的大小,直接一次开辟够Object对象和引用计数大小一样的空间,引用计数对象的mptr指针指向Object对象,在这个过程中在堆区的构建只new一次

这两种结构有什么区别呢?

在第一种方式中释放对象需要释放两次,而在第二种方式种释放对象只需要释放一次,而用第二种方式创建的对象在析构的时候也更加的复杂,需要更深入的编程

2.画出下面程序的内存分布图

class Object
{
private:
    int value;
public:
    Object(int x = 0) :value(x) {   cout << "Object" << endl;   }
    ~Object()   {   cout << "~Object" << endl;  }
};
template
class RefCnt
{
private:
    _Ty* mptr;
    int ref;
public:
    RefCnt(_Ty* p = nullptr) :mptr(p), ref(mptr != nullptr) {}
    ~RefCnt() {}
};

template
class my_shared_ptr
{
private:
    RefCnt<_Ty>* ptr;
public:
    my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
    {
        if (p != nullptr)
        {
            ptr = new RefCnt(p);
        }
    }
};
int main()
{
    std::shared_ptr sp1(new Object(10));
    std::shared_ptr sp2;

	return 0;
}
 


3.判断下面程序的引用计数各是多少?

class Object
{
private:
    int value;
public:
    Object(int x = 0) :value(x) {   cout << "Object" << endl;   }
    ~Object()   {   cout << "~Object" << endl;  }
};
template
class RefCnt
{
private:
    _Ty* mptr;
    int ref;
public:
    RefCnt(_Ty* p = nullptr) :mptr(p), ref(mptr != nullptr) {}
    ~RefCnt() {}
};

template
class my_shared_ptr
{
private:
    RefCnt<_Ty>* ptr;
public:
    my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
    {
        if (p != nullptr)
        {
            ptr = new RefCnt(p);
        }
    }
};
int main()
{
    std::shared_ptr sp1(new Object(10));
    std::shared_ptr sp2 = std::make_shared(20);

    std::shared_ptr  sp3;
    std::shared_ptr sp4(sp1);
    cout << sp1.use_count() << endl;//2
    cout << sp2.use_count() << endl;//1
    cout << sp3.use_count() << endl;//0
    cout << sp4.use_count() << endl;//2

    return 0;
}
 

4.拷贝构造函数和赋值函数执行完以后,两个对象是一模一样的,而移动构造和移动赋值的目的就是把A对象对资源的拥有权交给B对象,而A对象没有对资源的拥有权,通俗来讲就是资源转移了

int main()
{
	Object obj1;//普通构造
	Object obj2(obj1);//拷贝构造
	Object obj3(std::move(obj1));//移动构造
	obj1 = obj2;//普通赋值
	obj1 = std::move(obj2);//移动赋值
	
	return 0;
}

5.在C11标准中,有6个默认的函数,如果不写,编译器会自动为我们加上缺省的函数,有构造函数、析构函数、拷贝构造函数、赋值函数、对普通对象取地址符重载、对常对象取地址符重载,在C11标准以后,新增了移动构造和移动赋值,变成了8个默认的函数

class Object
{
private:
	int value;
public:
	//C11前
	Object() {}
	~Object() {}
	Object(const Object & src) {}
	Object& operator=(const Object& src) {}
	Object* operator&() { return this; }
	const Object* operator&() const { return this; }
	//C11后
	Object(Object&& src) {} //移动构造
	Object & operator=(Object && src) {} //移动赋值
};

6.面试的智能指针常问

7.循环引用

会导致两个对象都不能析构,因为循环引用会导致两个对象的引用计数都是2

class Child;
class Parent
{
public:
	shared_ptr child;
	Parent() { cout << "Parent" << endl; }
	~Parent() { cout << "~Parent" << endl; }
	void hi() { cout << "Hello" << endl; }
};
class Child
{
public:
	shared_ptr parent;
	Child() { cout << "Child" << endl; }
	~Child() { cout << "~Child" << endl; }
};
void fun()
{
	shared_ptr p = make_shared();
	shared_ptr c = make_shared();
	
	p->child = c;
	c->parent = p;
	c->parent->hi();
}
int main()
{
	
	return 0;
}

那么如何解决上面的问题呢?

答案:使用弱引用

8.对于引用计数ref,它的值不应该是一个整型值,因为整型值在多线程中进行自加自减时并没有安全性,因为它不是原子操作,但是可以通过引入头文件#include ,可以将int ref;替换成std::atomic(int) ref;这时使用ref进行加一减一或者和零值比较就具有原子性了,这样来说程序就相对安全一些

9.共享型智能指针全部代码

//Object对象
class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x) { cout << "Object" << endl; }
	~Object() { cout << "~Object" << endl; }
};
//处理一个对象的删除器
template
class MyDeletor
{
public:
	//MyDeletor() = default;
	MyDeletor() {}
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete ptr;
		}
	}
};

//处理一组对象的删除器
template
class MyDeletor<_Ty[]>
{
public:
	MyDeletor() = default;
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete[]ptr;
		}
	}
};

//引用计数
template
class RefCnt
{
public:
	_Ty* mptr;
	//int ref;
	std::atomic_int ref;
public:
	RefCnt(_Ty* p = nullptr) :mptr(p), ref(mptr != nullptr) {}
	~RefCnt() {}
};

//处理单个对象
template >
class my_shared_ptr // thread;
{
private:
	RefCnt<_Ty>* ptr;
	_Dx mDeletor;
public:
	my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
	{
		if (p != nullptr)
		{
			ptr = new RefCnt(p);
		}
	}
	my_shared_ptr(const my_shared_ptr& _Y) :ptr(_Y.ptr)
	{
		if (ptr != nullptr)
		{
			ptr->ref += 1;
		}
	}// my_shared_ptr op2(op1);
	my_shared_ptr(my_shared_ptr&& _Y) :ptr(_Y.ptr)
	{
		_Y.ptr = nullptr;
	}// my_shared_ptr op2(std::move(op1));
	operator bool() const { return ptr != nullptr; }
	my_shared_ptr& operator=(const my_shared_ptr& _Y) // 
	{
		if (this == &_Y || this->ptr == _Y.ptr) return *this;
		if (ptr != NULL && --ptr->ref == 0)
		{
			mDeletor(ptr);
		}
		ptr = _Y.ptr;
		if (ptr != nullptr)
		{
			ptr->ref += 1;
		}
		return *this;
	}
	my_shared_ptr& operator=(my_shared_ptr&& _Y) // move operator =
	{
		if (this == &_Y) return *this;
		if (this->ptr == _Y.ptr && this->ptr != nullptr && _Y.ptr != nullptr)
		{
			this->ptr->ref -= 1;
			_Y.ptr = nullptr;
			return * this;
		}
		if (this->ptr != nullptr && --ptr->ref == 0)
		{
			mDeletor(ptr);
		}
		ptr = _Y.ptr;
		_Y.ptr = nullptr;
		return *this;
	}
	void reset(_Ty* p = nullptr)
	{
		if (this->ptr != nullptr && --this->ptr->ref == 0)
		{
			mDeletor(ptr);
		}
		ptr = new RefCnt<_Ty>(p);
	}
	~my_shared_ptr()
	{
		if (this->ptr != nullptr && --this->ptr->ref == 0)
		{
			mDeletor(ptr->mptr);
			delete ptr;
		}
		ptr = nullptr;
	}
	_Ty* get() const { return ptr->mptr; }
	_Ty& operator*() const
	{
		return *get();
	}
	_Ty* operator->() const
	{
		return get();
	}
	size_t use_count() const
	{
		if (this->ptr == nullptr) return 0;
		return this->ptr->ref;
	}
	void swap(my_shared_ptr& r)
	{
		std::swap(this->ptr, r.ptr);
	}
};

//处理一组对象
template
class my_shared_ptr<_Ty[],_Dx>
{
private:
	RefCnt<_Ty>* ptr;
	_Dx mDeletor;
public:
	my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
	{
		if (p != nullptr)
		{
			ptr = new RefCnt(p);
		}
	}
	my_shared_ptr(const my_shared_ptr& _Y) :ptr(_Y.ptr)
	{
		if (ptr != nullptr)
		{
			ptr->ref += 1;
		}
	}// my_shared_ptr op2(op1);
	my_shared_ptr(my_shared_ptr&& _Y) :ptr(_Y.ptr)
	{
		_Y.ptr = nullptr;
	}// my_shared_ptr op2(std::move(op1));
	operator bool() const { return ptr != nullptr; }
	my_shared_ptr& operator=(const my_shared_ptr& _Y) // 
	{
		if (this == &_Y || this->ptr == _Y.ptr) return *this;
		if (ptr != NULL && --ptr->ref == 0)
		{
			mDeletor(ptr->mptr);
			delete ptr;
		}
		ptr = _Y.ptr;
		if (ptr != nullptr)
		{
			ptr->ref += 1;
		}
		return *this;
	}
	my_shared_ptr& operator=(my_shared_ptr&& _Y) // move operator =
	{
		if (this == &_Y) return *this;
		if (this->ptr == _Y.ptr && this->ptr != nullptr && _Y.ptr != nullptr)
		{
			this->ptr->ref -= 1;
			_Y.ptr = nullptr;
			return * this;
		}
		if (this->ptr != nullptr && --ptr->ref == 0)
		{
			mDeletor(ptr->mptr);
			delete ptr;
		}
		ptr = _Y.ptr;
		_Y.ptr = nullptr;
		return *this;
	}
	void reset(_Ty* p = nullptr)
	{
		if (this->ptr != nullptr && --this->ptr->ref == 0)
		{
			mDeletor(ptr->mptr);
			delete ptr;
		}
		ptr = new RefCnt<_Ty>(p);
	}
	~my_shared_ptr()
	{
		if (this->ptr != nullptr && --this->ptr->ref == 0)
		{
			mDeletor(ptr->mptr);
			delete ptr;
		}
		ptr = nullptr;
	}
	_Ty* get() const { return ptr->mptr; }
	_Ty& operator*() const
	{
		return *get();
	}
	_Ty* operator->() const
	{
		return get();
	}
	size_t use_count() const
	{
		if (this->ptr == nullptr) return 0;
		return this->ptr->ref;
	}
	void swap(my_shared_ptr& r)
	{
		std::swap(this->ptr, r.ptr);
	}
	_Ty& operator[](const int idx) const
	{
		return ptr->mptr[idx];
	}
};


转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号