令一个类展现类似于指针行为的最好方法是使用shared_ptr来管理类中的资源。
拷贝(赋值)一个shared_ptr会拷贝(赋值)shared_ptr所指向的指针(可以认为shared_ptr有一个引用计数器);当没有用户使用对象时,shared_ptr类自己会释放资源。智能指针比普通指针的好处主要有2点:1、不需要自己手动delete 2、避免delete掉一个还有指针引用的内存(正确的时间释放内存)
解决思路:
那么如何设计自己的类,使其行为像智能指针呢,使用引用计数就可以实现,将计数器保存在动态内存中,创建一个对象时,分配一个新计数器,拷贝(赋值)对象时,拷贝指向这个计数器的内存,这样副本和原对象都指向相同的计数器。
h文件
#pragma once #include <string> using namespace std; class HasPtr { public: HasPtr(const string &s); HasPtr(const HasPtr&); HasPtr& operator=(const HasPtr &rhs); ~HasPtr(); private: size_t *use; string *pString; };
cpp文件
#include "stdafx.h" #include "HasPtr.h" #include <string> HasPtr::HasPtr(const string &s=string()):pString(new string(s)),use(new size_t(1)) { } HasPtr::HasPtr(const HasPtr &p) { pString = p.pString; use = p.use; ++*use; } HasPtr& HasPtr::operator=(const HasPtr &rhs) { ++*rhs.use;//防止自己拷贝自己出错 if (--*use == 0) { delete pString; delete use; } pString = rhs.pString; use = rhs.use; return *this; } HasPtr::~HasPtr() { if (--*use == 0) { delete pString; delete use; } }
main.cpp
#include "stdafx.h" #include "HasPtr.h" int main() { HasPtr p1("come here"); HasPtr p2(p1);//拷贝构造 HasPtr p3 = p2;//拷贝构造 p3 = p2;//拷贝赋值 return 0; }
拷贝构造出现在一个初始化和一个未初始化的变量里,
拷贝赋值出现在2个已经初始化的变量里;
拷贝赋值运算符为什么会返回一个指向其左侧运算对象的引用?
答:1、与内置类型的赋值保持一致
2、标准库要求保存在容器的类型要具有赋值运算符,且其返回值时左侧运算对象的引用
eg: a=b=c;如果没有返回值,就会出错
通过断点一步步调试就会发现每一步的运行步骤