只写了MinGw/Linux API部分。所有相关的代码都是参考C++ API
C++ 11智能指针参考http://blog.csdn.net/zy19940906/article/details/50470087
<1>Pimpl
pointer to the implementation
计算一个累构造消耗的时间。
AutoTimer.h
//
// Created by Administrator on 2017/3/26.
// #ifndef MODERN_DESIGN_AUTOTIMER_H
#define MODERN_DESIGN_AUTOTIMER_H
#include <iostream>
#include <string>
#include <memory>
class AutoTimer
{
public:
explicit AutoTimer(const std::string &name);
~AutoTimer();
private:
class Impl;
Impl *_mimpl;
// std::unique_ptr <Impl> _mimpl; //智能指针,生命周期与类成员周期相同
}; #endif //MODERN_DESIGN_AUTOTIMER_H
AutoTimer.cpp
#include "AutoTimer.h"
#include <sys/time.h>
class AutoTimer::Impl
{
public:
double getElapsed() const
{
timeval end_time;
gettimeofday(&end_time,NULL);
double t1 = _start_time.tv_usec / 1e6 + _start_time.tv_sec;
double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec;
return t2 - t1;
}
std::string _name;
timeval _start_time;
};
AutoTimer::AutoTimer(const std::string &name):_mimpl(new AutoTimer::Impl())
{
_mimpl->_name = name;
gettimeofday(&_mimpl->_start_time,NULL);
}
AutoTimer::~AutoTimer()
{
std::cout << _mimpl->_name << ":took " << _mimpl->getElapsed() << " secs" <<std::endl;
delete _mimpl; // 如果是智能指针不需用
_mimpl= NULL; // 如果是智能指针不需用
}
main.cpp:
AutoTimer timer("Houdini");
AutoTimer timer2("Maya");
输出:
Maya:took 0.000999928 secs
Houdini:took 0.000999928 secs
C语言的不透明指针。。。。实现就是这么轻松随意。。。。
AutoTimer.h
#ifndef MODER_DESIGN_C_AUTOTIMER_H
#define MODER_DESIGN_C_AUTOTIMER_H
// 声明一个指向AutoTimer结构体不透明的指针
typedef struct AutoTimer *AutoTimerPtr;
AutoTimerPtr AutoTimerCreate(const char *name);
void AutoTimerDestroy(AutoTimerPtr ptr); #endif //MODER_DESIGN_C_AUTOTIMER_H
AutoTimer.cc
#include "AutoTimer.h"
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h> struct AutoTimer
{
char *mName;
timeval mStartTime;
}; AutoTimerPtr AutoTimerCreate(const char *name)
{
AutoTimerPtr ptr = static_cast<AutoTimerPtr> (malloc(sizeof(AutoTimer))); // 因为我们用的是C++编译器,所以还是显式转换
if(ptr)
{
ptr->mName = strdup(name);
gettimeofday(&ptr->mStartTime,NULL);
}
return ptr;
}
static double GetElapsed(AutoTimerPtr ptr)
{
timeval end_time;
gettimeofday(&end_time,NULL);
double t1 = ptr->mStartTime.tv_usec / 1e6 + ptr->mStartTime.tv_sec;
double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec;
return t2-t1;
}
void AutoTimerDestroy(AutoTimerPtr ptr)
{
if(ptr)
{
printf("%s took %f secs\n",ptr->mName,GetElapsed(ptr));
free(ptr);
}
}
main.cpp
AutoTimerPtr ptr = AutoTimerCreate("Houdini");
AutoTimerDestroy(ptr); AutoTimerPtr ptr2 = AutoTimerCreate("Maya");
AutoTimerDestroy(ptr2);
输出:
Houdini took 0.000000 secs
Maya took 0.000000 secs
Hello, World!
<2> 单例模式:
#include <iostream>
#include <thread>
#include <mutex>
using namespace std; class Singleton
{
public: static Singleton &GetInstance()
{
static Singleton *instance = NULL;
if(! instance)
{
std::mutex mutex;
if(! instance)
{
instance = new Singleton();
}
mutex.unlock();
}
return *instance;
}
static Singleton *GetInstancev2()
{
static Singleton m_instance;
return &m_instance;
} private:
Singleton()
{ }
~Singleton()
{ }
Singleton(const Singleton &);
const Singleton &operator=(const Singleton &); }; void threadFunc(string name,int uniqueId)
{
std::cout << "Singleton meomery:" << name << " -> " << uniqueId << " :Object &"<<&Singleton::GetInstance() <<"\n";
}
void threadRun()
{
thread thread_01(threadFunc,"houdini",);
thread thread_02(threadFunc,"maya",);
thread thread_03(threadFunc,"blender",); thread_01.join();
thread_02.join();
thread_03.join(); } int main()
{
Singleton &obj = Singleton::GetInstance();
std::cout << &obj <<std::endl;
//
std::cout << "test in thread \n";
threadRun(); // test use another
std::cout << "GetInstancev2 method create \n";
Singleton *obj2 = Singleton::GetInstancev2();
std::cout << obj2 <<std::endl; Singleton *obj3 = Singleton::GetInstancev2();
std::cout << obj3 << std::endl;
return ;
}
输出:
0x3e67c0
test in thread
Singleton meomery:Singleton meomery:blender -> Singleton meomery:maya -> houdini -> 0 :Object &0x3e67c0
1 :Object &0x3e67c0
2 :Object &0x3e67c0
GetInstancev2 method create
0x4060b0
0x4060b0
<3> 工厂模式
<4> 写时复制,节省内存最好的方法就是确实需要时再分配。所有客户共享一份唯一的资源,直到其中一个想修改这份资源为止,只有在哪个时间点才回构造副本.
template <class T> class CowPtr
{
public:
using RefPtr = std::shared_ptr<T> ;
inline CowPtr():mPtr(){}
inline CowPtr(const CowPtr<T> &other):mPtr(other.mPtr)
{
std::cout << "copy function "<< __LINE__<< "\n";
}
inline explicit CowPtr(T *other):mPtr(other){}
inline T &operator*()
{
std::cout<< "inline T &operator*()" <<__LINE__<<std::endl;
Detach();
return *(mPtr.get());
}
inline const T &operator*() const {
std::cout<< "inline const T &operator*() const" <<__LINE__<<std::endl;
return *(mPtr.get());
}
inline T*operator->()
{
std::cout<< "inline T*operator->()" <<__LINE__<<std::endl;
Detach();
return mPtr.get();
}
inline const T*operator->() const {
std::cout<< "inline const T*operator->() " << __LINE__<<std::endl;
return mPtr.get();
} inline const T*data()const
{
std::cout<< "inline const T*data()const " << __LINE__<<std::endl;
return mPtr.get();
} inline bool operator==(const CowPtr<T> &other) const {
return mPtr.get() == other.mPtr.get();
} inline bool operator!() const
{
return !mPtr.get();
}
inline CowPtr &operator=(T *other)
{
mPtr = RefPtr(other);
return *this;
} private:
inline void Detach()
{
T *temp = mPtr.get();
if(temp && !mPtr.unique())
{
mPtr = RefPtr(new T(*temp)); //
}
}
RefPtr mPtr; }; class WriteOnCopy
{
public:
WriteOnCopy(){}
std::string getValue() const
{
return *mData; }
void setValue(const std::string &value)
{
mData = new std::string(value);
} private:
CowPtr<std::string> mData;
}; int main()
{
CowPtr<std::string> string1(new std::string("houdini"));
CowPtr<std::string> string2(string1); //copy function
CowPtr<std::string> string3(string1); //copy function
string3->append("!!");
std::cout << *string3.data()<<std::endl; //houdini!!
std::cout << *string1<<std::endl; // houdini std::cout << "\n after change 1 \n";
CowPtr<std::string> pr_string1(new std::string("share me"));
char &char_ref = pr_string1->operator[](); //use the string operator[] function
CowPtr<std::string> pr_string2(pr_string1);
char_ref = 'H'; // after change 'H'
std::cout << *(pr_string1.data())<<std::endl; //sHare me
std::cout << *(pr_string2.data())<<std::endl; //sHare me // use write on copy
std::cout << "\nwrite on copy\n";
WriteOnCopy obj1;
obj1.setValue("hello");
WriteOnCopy obj2 = obj1;
std::string val = obj2.getValue();
WriteOnCopy obj3 = obj1;
obj3.setValue("There");
std::cout << "obj1 get data " << obj1.getValue() <<std::endl;
std::cout << "obj2 get data " << obj2.getValue() <<std::endl;
std::cout << "obj3 get data " << obj3.getValue() <<std::endl; return ;
}
<5>CPP Style
(1)更好的重载operator
GLY_Currency.h
#ifndef CPPSTYLE_GLY_CURRENCY_H
#define CPPSTYLE_GLY_CURRENCY_H #include <memory>
#include <iostream>
class GLY_Currency
{
public:
explicit GLY_Currency(int value);
~GLY_Currency();
GLY_Currency(const GLY_Currency&obj);
int getValue()const; // these operators must be declared as member functions
GLY_Currency &operator = (const GLY_Currency &rhs);
GLY_Currency &operator += (const GLY_Currency &rhs);
GLY_Currency &operator -= (const GLY_Currency &rhs);
GLY_Currency &operator *= (const GLY_Currency &rhs);
GLY_Currency &operator /= (const GLY_Currency &rhs); private:
class Impl;
std::unique_ptr <Impl> mImpl;
}; // these operators can (and should) be declared as free functions
inline GLY_Currency operator+(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
// 复制一份是因为lhs+=rhs 会导致 lhs更改数据,因为lhs是const,所以不用复制构造,会导致
// 编译错误
return GLY_Currency(lhs)+=rhs;
}
inline GLY_Currency operator-(const GLY_Currency &lhs ,const GLY_Currency &rhs)
{
return GLY_Currency(lhs)-=rhs;
}
inline GLY_Currency operator*(const GLY_Currency &lhs ,const GLY_Currency &rhs)
{
return GLY_Currency(lhs)*=rhs;
}
GLY_Currency operator /(const GLY_Currency &lhs, const GLY_Currency &rhs)
{
return GLY_Currency(lhs) /= rhs;
} inline bool operator==(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
return lhs.getValue()==rhs.getValue();
} inline bool operator!=(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
return !(lhs==rhs);
}
inline bool operator<(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
return rhs.getValue()<rhs.getValue();
}
inline bool operator>(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
return rhs < lhs;
} inline bool operator<=(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
return !(rhs > rhs);
}
inline bool operator>=(const GLY_Currency &lhs,const GLY_Currency &rhs)
{
return rhs <= lhs;
} inline std::ostream &operator <<(std::ostream &os,const GLY_Currency &rhs)
{
os << rhs.getValue();
return os;
} #endif //CPPSTYLE_GLY_CURRENCY_H
GLY_Currency.cpp
//
// Created by Administrator on 2017/5/2.
// #include "GLY_Currency.h"
class GLY_Currency::Impl
{
public:
int mValue;
}; GLY_Currency::GLY_Currency(int value):mImpl(new Impl)
{
mImpl->mValue = value;
}
GLY_Currency::~GLY_Currency() { } GLY_Currency::GLY_Currency(const GLY_Currency &obj):mImpl(new Impl)
{
mImpl->mValue = obj.mImpl->mValue;
}
int GLY_Currency::getValue() const {
return mImpl->mValue;
} GLY_Currency& GLY_Currency::operator=(const GLY_Currency &rhs) {
if (this != &rhs)
{
mImpl->mValue = rhs.mImpl->mValue;
}
return *this;
}
GLY_Currency& GLY_Currency::operator-=(const GLY_Currency &rhs) {
mImpl->mValue -= rhs.mImpl->mValue;
return *this;
}
GLY_Currency& GLY_Currency::operator+=(const GLY_Currency &rhs) {
mImpl->mValue += rhs.mImpl->mValue;
return *this;
} GLY_Currency& GLY_Currency::operator*=(const GLY_Currency &rhs) {
mImpl->mValue *= rhs.mImpl->mValue;
return *this;
}
GLY_Currency& GLY_Currency::operator/=(const GLY_Currency &rhs) {
mImpl->mValue /= rhs.mImpl->mValue;
return *this;
}
<6>Exception Basic
#include <iostream> /*
// BASIC
template <typename T>
T safe_divide(T const&a,T const &b)
{
if (b == 0)
{
const char *error = "b is zero do not allowed ";
throw error;
}
return a/b;
} int main()
{
double result = 0.0 ;
try
{
result = safe_divide(2.0,0.0);
}
catch (const char*s)
{
std::cout << s <<std::endl; // will get const char *error = "b is zero do not allowed " //try to use right arg
result = safe_divide(2.0,1.0);
} std::cout << result <<std::endl;
return 0;
}*/ // Use class handle the error
class ClassBad_divide_Except
{
private:
double v1;
double v2;
public:
ClassBad_divide_Except(double a=0.0,double b=0.0):v1(a),v2(b){ }
void mesg()
{
const char* mesgs = "Error divide argments :";
std::cout <<mesgs << v1<<"/"<<v2<<std::endl;
}
}; template <typename T>
T safe_divide(T const&a,T const &b)
{
if (b == )
{
const char *error = "b is zero do not allowed ";
throw ClassBad_divide_Except(a,b); //emit a class instance ClassBad_divide_Except()
}
return a/b;
} int main()
{
double result = 0.0 ;
try
{
result = safe_divide(2.0,0.0);
}
catch (ClassBad_divide_Except &did) // get class ref
{
did.mesg(); // get error message //try to use right arg
result = safe_divide(2.0,1.0);
} std::cout << result <<std::endl;
return ;
}
<7> RTTI
RTTI just compatable for a class have a virtual method