类型转换
构造函数:其他数据类型——>自定义数据类型
类型转换函数:自定义数据类型——>其他数据类型
但一般情况下不要使用
类型转换函数特点
- 是成员函数
- 没有返回值类型
- 在函数体内以传值形式返回一个目标类型的变量(对象)
PIMPL设计模式
简介
是一种常用的用来对“类的接口和实现”进行解耦的方法,以避免在头文件中暴露私有细节。但PIMPL并非严格意义上的设计模式,可看作是桥接设计模式的一种特例。
作用
- 实现信息隐藏
- 降低编译依赖
- 以最小代价完成库的平滑升级
示例
Line.h
#pragma once
#include <iostream>
using namespace std;
class Line
{
public:
Line();
Line(int,int,int,int);
~Line();
void printLine();
private:
class LinePimpl;
LinePimpl *_pimpl;
};
LinePimpl.cc
#include "Line.h"
class Line::LinePimpl
{
//定义点类
class Point
{
public:
Point(int x,int y)
: _ix(x), _iy(y)
{
cout << "Point::Point(int x, int y)" << endl;
}
~Point()
{
cout << "Point::~Point()" << endl;
}
void printPoint()
{
cout << "(" << _ix << ", " << _iy << ")" << endl;
}
private:
int _ix;
int _iy;
};
private:
Point _pt1;
Point _pt2;
public:
LinePimpl(int x1, int y1, int x2, int y2)
: _pt1(x1, y1), _pt2(x2, y2)
{
cout << "LinePimpl::LinePimpl(int x1, int y1, int x2, int y2)" << endl;
}
~LinePimpl()
{
cout << "LinePimpl::~LinePimpl()" << endl;
}
void printPimpl()
{
_pt1.printPoint();
cout << "------>" << endl;
_pt2.printPoint();
}
};
Line::Line()
{
cout << "Line::Line()" << endl;
}
Line::Line(int x1, int y1, int x2, int y2)
:_pimpl(new LinePimpl(x1,y1,x2,y2))
{
cout << "Line::Line()" << endl;
}
Line::~Line()
{
if(_pimpl)
delete _pimpl;
cout << "Line::~Line()" << endl;
}
void Line::printLine()
{
_pimpl->printPimpl();
}
main.cc
#include "Line.h"
int main(int argc, char *argv[])
{
Line line(1,2,3,4);
line.printLine();
return 0;
}
单例对象的自动回收
作用:避免对程序进行内存泄漏检查时造成不必要的麻烦
嵌套类+静态对象(多线程不安全)
#include <iostream>
using namespace std;
class Singleton
{
class autoRelease
{
public:
autoRelease() { cout << "autoRelease()" << endl; }
~autoRelease() {
cout << "~autoRelease()" << endl;
if(_pinstance)
delete _pinstance;
}
};
public:
static Singleton *getinstance()
{
if(_pinstance == nullptr)
_pinstance = new Singleton();
return _pinstance;
}
private:
Singleton() { cout << "Sinleton()" << endl; }
~Singleton() { cout << "~Singleton()" << endl; }
static autoRelease _auto;
static Singleton *_pinstance;
};
Singleton *Singleton::_pinstance = nullptr;
Singleton::autoRelease Singleton::_auto;
int main(int argc, char *argv[])
{
Singleton *p1 = Singleton::getinstance();
Singleton *p2 = Singleton::getinstance();
cout << p1 << endl << p2 << endl;
return 0;
}
静态成员函数+atexit()
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getinstance()
{
if(_pinstance == nullptr)
{
atexit(destory);
_pinstance = new Singleton();
}
return _pinstance;
}
static void destory()
{
if(_pinstance)
delete _pinstance;
}
private:
Singleton(){ cout << "Singleton()" << endl; }
~Singleton(){ cout << "~Singleton()" << endl; };
static Singleton *_pinstance;
};
Singleton * Singleton::_pinstance = nullptr;
int main(int argc, char *argv[])
{
Singleton *p1 = Singleton::getinstance();
Singleton *p2 = Singleton::getinstance();
cout << p1 << endl << p2 << endl;
return 0;
}
pthread_once() +atexit() (多线程安全,推荐使用)
#include <cstdlib>
#include <pthread.h>
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton *getinstance()
{
pthread_once(&_once, init);
return _pinstance;
}
static void init()
{
atexit(destory);
if(_pinstance == nullptr)
_pinstance = new Singleton();
}
static void destory()
{
if(_pinstance)
delete _pinstance;
}
private:
Singleton(){ cout << "Singleton()" << endl; }
~Singleton(){ cout << "~Singleton()" << endl; }
static Singleton *_pinstance;
static pthread_once_t _once;
};
Singleton *Singleton::_pinstance = nullptr;
pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;
int main(int argc, char *argv[])
{
Singleton *p1 = Singleton::getinstance();
Singleton *p2 = Singleton::getinstance();
cout << p1 << endl << p2 << endl;
return 0;
}
std::string的底层实现
Eager-Copy
COW
全称为Copy-On-Write,即写时复制:当对字符串进行复制或赋值时,并不马上真正进行赋值,只有当字符串的内容要进行修改时,才进行深拷贝
实现代码
#include <cstring>
#include <iostream>
using namespace std;
class CowString
{
class CharProxy
{
public:
CharProxy(CowString& self, int idx)
:_self(self)
,_idx(idx)
{
cout << "CharProxy(CowString& self, int idx)" << endl;
}
~CharProxy()
{
cout << "~CharProxy()" << endl;
}
operator char()
{
return _self._pstr[_idx];
}
char &operator=(const char &ch);
private:
CowString &_self;
int _idx;
};
public:
CowString()
:_pstr(new char[5]()+4)
{
*(_pstr-4) = '\0';
initref();
cout << "CowString()" << endl;
}
CowString(const char *pstr)
:_pstr(new char[strlen(pstr)+5]()+4)
{
cout << "CowString(const char *pstr)" << endl;
strcpy(_pstr, pstr);
initref();
}
CowString(const CowString& rhs)
:_pstr(rhs._pstr)
{
cout << "CowString(const CowString& rhs)" << endl;
increaseref();
}
CowString& operator=(const CowString& rhs)
{
cout << "CowString& operator=(const CowString& rhs)" << endl;
if(this != &rhs)
{
release();
_pstr = rhs._pstr;
increaseref();
}
return *this;
}
int length()
{
return *(int*)(_pstr-4);
}
const char *c_str()
{
return _pstr;
}
void showref()
{
cout << *(int*)(_pstr-4) << endl;
}
friend std::ostream &operator<<(std::ostream &os, const CowString &rhs);
CharProxy operator[](int idx);
private:
void initref()
{
*(int *)(_pstr-4) = 1;
}
void increaseref()
{
++*(int *)(_pstr-4);
}
void decreaseref()
{
--*(int *)(_pstr-4);
}
void release()
{
decreaseref();
if(*(int *)(_pstr-4) == 0)
delete [](_pstr-4);
}
char *_pstr;
};
CowString::CharProxy CowString::operator[](int idx)
{
return CharProxy(*this, idx);
}
std::ostream &operator<<(std::ostream &os, const CowString &rhs)
{
cout << rhs._pstr;
return os;
}
char &CowString::CharProxy::operator=(const char &ch)
{
if(_idx >= 0 && _idx < _self.length())
{
if(*(int*)(_self._pstr-4) > 1)
{
_self.release();
char *tmp = new char[strlen(_self._pstr)+5]()+4;
strcpy(tmp, _self._pstr);
_self._pstr = tmp;
_self.initref();
}
_self._pstr[_idx] = ch;
return _self._pstr[_idx];
}
else
{
static char nullchar = '\0';
return nullchar;
}
}
int main(int argc, char *argv[])
{
CowString s1 = "hello,world";
CowString s2 = s1;
CowString s3 = "shenzhen";
cout << "s3 = " << s3 << endl;
s3 = s1;
cout << "执行赋值操作之后:" << endl;
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
printf("s1's address is %p\n", s1.c_str());
printf("s2's address is %p\n", s2.c_str());
printf("s3's address is %p\n", s3.c_str());
cout << "s1's refcount = " << endl;
s1.showref();
cout << "s2's refcount = "<< endl;
s2.showref();
cout << "s3's refcount = "<< endl;
s3.showref();
cout << "\n 修改共享字符串的内容之后:" << endl;
s3[0] = 'X';
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
printf("s1's address is %p\n", s1.c_str());
printf("s2's address is %p\n", s2.c_str());
printf("s3's address is %p\n", s3.c_str());
cout << "s1's refcount = " << endl;
s1.showref();
cout << "s2's refcount = "<< endl;
s2.showref();
cout << "s3's refcount = "<< endl;
s3.showref();
cout << "\n 执行读操作之后:" << endl;
cout << "s1[0] = " << s1[0] << endl;
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
printf("s1's address is %p\n", s1.c_str());
printf("s2's address is %p\n", s2.c_str());
printf("s3's address is %p\n", s3.c_str());
cout << "s1's refcount = " << endl;
s1.showref();
cout << "s2's refcount = "<< endl;
s2.showref();
cout << "s3's refcount = "<< endl;
s3.showref();
return 0;
}
SSO
全称为Short-String-Optimazation,即短字符串优化:当字符串长度<=15个字节时,字符串内容作为对象的一部分,否则,该字符串用堆空间进行存储