前言
繼續閱讀之前,你最好了解了左值,右值,左值引用,右值引用等概念
引入
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class CMyString
{
public:
CMyString(char* pStr)
: m_pStr(NULL)
, m_nLen(0)
{
if (NULL != pStr)
{
m_nLen = strlen(pStr);
m_pStr = new char[m_nLen + 1];
memcpy(m_pStr, pStr, m_nLen);
m_pStr[m_nLen] = 0;
cout << "一般構造函數 str=" << m_pStr << endl;
}
}
CMyString(const CMyString& o)
: m_pStr(NULL)
, m_nLen(0)
{
if (NULL != o.m_pStr)
{
m_nLen = o.m_nLen;
m_pStr = new char[m_nLen + 1];
memcpy(m_pStr, o.m_pStr, m_nLen);
m_pStr[m_nLen] = 0;
cout << "拷貝構造函數 str=" << m_pStr << endl;
}
}
const CMyString& operator=(const CMyString& o)
{
if (this != &o)
{
if (NULL != m_pStr)
{
delete[] m_pStr;
m_pStr = NULL;
}
m_nLen = o.m_nLen;
if (NULL != o.m_pStr)
{
m_pStr = new char[m_nLen + 1];
memcpy(m_pStr, o.m_pStr, m_nLen);
m_pStr[m_nLen] = 0;
}
cout << "重載賦值運算符 str=" << m_pStr << endl;
}
return *this;
}
~CMyString()
{
if (NULL != m_pStr)
{
//cout << "析構函數 str=" << m_pStr << endl;
delete m_pStr;
}
}
char* GetData()
{
return m_pStr;
}
private:
char* m_pStr;
int m_nLen;
};
void swap(CMyString& str1, CMyString& str2)
{
cout << "********************************************" << endl;
CMyString tmp = str1;
str1 = str2;
str2 = tmp;
cout << "********************************************" << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
CMyString str1("hello this is str1");
CMyString str2("hello this is str2");
swap(str1, str2);
cout << "str1.GetData:" << str1.GetData() << endl;
cout << "str2.GetData:" << str2.GetData() << endl;
system("pause");
}
void swap(CMyString& o)
{
char* pStrTmp = o.m_pStr;
int nLen = o.m_nLen;
o.m_pStr = m_pStr;
o.m_nLen = m_nLen;
m_pStr = pStrTmp;
m_nLen = nLen;
}
交換的時候使用str1.swap(str2);
看一下執行結果通過直接交換內部數據指針的方式,成功交換了兩個值,省去了很多無意義的new delete操作(實際std::string::swap函數實現原理類似)
進階
CMyString GetCMyString()
{
return CMyString("hello this is the other one");
}
int _tmain(int argc, _TCHAR* argv[])
{
CMyString str("this is str");
// use str do something
// fun(str);
str = GetCMyString();
system("pause");
return 0;
}
如上代碼我們構建str並在fun中執行一系列操作之後使用GetCMyString給str賦予了新的值,執行效果如下: const CMyString& operator=(CMyString& o)
{
char* pStrTmp = o.m_pStr;
int nLen = o.m_nLen;
o.m_pStr = m_pStr;
o.m_nLen = m_nLen;
m_pStr = pStrTmp;
m_nLen = nLen;
return *this;
}
執行效果如下:CMyString str("this is str");
CMyString strImp("this is strimp");
str = strImp;
cout << "strImp.GetData:" << strImp.GetData() << endl;
system("pause");
const CMyString& operator=(CMyString&& o)
{
char* pStrTmp = o.m_pStr;
int nLen = o.m_nLen;
o.m_pStr = m_pStr;
o.m_nLen = m_nLen;
m_pStr = pStrTmp;
m_nLen = nLen;
cout << "右值引用類型 重載賦值運算符 str=" << m_pStr << endl;
return *this;
}
測試一下:int _tmain(int argc, _TCHAR* argv[])
{
CMyString str("this is str");
CMyString strImp("this is strimp");
// use str do something
// fun(str);
str = GetCMyString();
cout << "str.GetData:" << str.GetData() << endl;
str = strImp;
cout << "strImp.GetData:" << strImp.GetData() << endl;
system("pause");
return 0;
}
CMyString(CMyString&& o)
: m_pStr(NULL)
, m_nLen(0)
{
char* pStrTmp = o.m_pStr;
int nLen = o.m_nLen;
o.m_pStr = m_pStr;
o.m_nLen = m_nLen;
m_pStr = pStrTmp;
m_nLen = nLen;
cout << "右值引用類型 拷貝構造函數 str=" << m_pStr << endl;
}
move
void swap(CMyString& str1, CMyString& str2)
{
cout << "********************************************" << endl;
CMyString tmp = str1;
str1 = str2;
str2 = tmp;
cout << "********************************************" << endl;
}
void swap(CMyString& o)
{
char* pStrTmp = o.m_pStr;
int nLen = o.m_nLen;
o.m_pStr = m_pStr;
o.m_nLen = m_nLen;
m_pStr = pStrTmp;
m_nLen = nLen;
}
之前我們發現,普通swap函數中的tmp對象帶來了多餘的new delete操作,我們使用swap成員函數優化掉了,如果不用swap成員函數來進行優化,有辦法嗎?swap改造如下:
void swap(CMyString& str1, CMyString& str2)
{
cout << "********************************************" << endl;
CMyString tmp = std::move(str1);
str1 = std::move(str2);
str2 = std::move(tmp);
cout << "********************************************" << endl;
}
測試一下:int _tmain(int argc, _TCHAR* argv[])
{
CMyString str1("hello this is str1");
CMyString str2("hello this is str2");
swap(str1, str2);
cout << "str1.GetData" << str1.GetData() << endl;
cout << "str2.GetData" << str2.GetData() << endl;
system("pause");
}