二级指针和指针的引用之间的区别

    技术2024-07-25  16

    看资料说: 指针的引用不会产生临时变量, 不会产生拷贝操作.

     

    我自己的多余体会: 指针的引用在实际编码时,操作比二级指针简单, 书写简洁.

     

    做个实验验证下.

     

    <2011_0201_2145>

    实验完成, 得出实验结论.

    /** * 下面的2句实验函数传进了二级指针和指针的引用 * 实验结论: * 只要传的是指针, 二级指针, 指针的引用, 都不会发生对象的拷贝, 也不会产生临时对象 * 传 xx*& 写代码时要简洁清晰一些 * * 遗留问题: * CClassTest::CClassTest(const CClassTest * prhs)这个自己推测的拷贝构造函数 * 从来没看调用进过这个函数, 莫非这是传指针不会进行拷贝构造临时对象的一个辅助证明? */ pClassA->CopyBufIflhsHasEnoughLength(&pClassB);//传的是CClassTest** pClassA->CopyBufIflhsHasEnoughLength(pClassB);//传的是CClassTest*&

     

    做这个实验时,顺便做了下类拷贝构造的实验.

    // DiffPpPRef.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "DiffPpPRef.h" #include "ClassTest.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif / // The one and only application object CWinApp theApp; using namespace std; void nFnTestPP();//测试二级指针 void nFnTestPRef();//测试指针的引用 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; // initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T("Fatal Error: MFC initialization failed") << endl; nRetCode = 1; } else { nFnTestPP(); nFnTestPRef(); } return nRetCode; } void nFnTestPP() { CClassTest * pClassA = NULL;//不会进入默认构造函数 CClassTest * pClassB = NULL;//不会进入默认构造函数 CClassTest ClassC;//进入默认构造函数 CClassTest ClassD;//进入默认构造函数 CClassTest ClassTmp; CClassTest * pClassIDMax = NULL; pClassA = new CClassTest;//进入默认构造函数 pClassA->SetBuf("新new出来的ClassA"); pClassA->SetID(1); pClassA->Dump("pClassA"); /** @note 运行结果 ---------------------------------------- CClassTest[pClassA] Infomation: Addr[00382818] m_pBuf => Addr[0038281C], Value[新new出来的ClassA] m_dwID => Addr[00382820], Value[1] ---------------------------------------- */ pClassB = pClassA;//没有拷贝发生, 指向同一个对象 pClassB->Dump("pClassB"); /** @note 运行结果 ---------------------------------------- CClassTest[pClassB] Infomation: Addr[00382818] m_pBuf => Addr[0038281C], Value[新new出来的ClassA] m_dwID => Addr[00382820], Value[1] ---------------------------------------- */ pClassB = new CClassTest; ClassC = *pClassA;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) ClassD = ClassC;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) *pClassB = *pClassA;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) pClassB->Dump("pClassB Copy From pClassA");//有拷贝发生 *pClassB = pClassA;//进入 CClassTest* CClassTest::operator= (CClassTest* prhs) ClassD = pClassB;//进入 CClassTest* CClassTest::operator= (CClassTest* prhs) TRACE("bp/n"); //类作为函数形参时, 进入CClassTest::CClassTest(const CClassTest & rhs) //进入函数时,产生临时对象, 发生了对象的拷贝 pClassIDMax = ClassTmp.GetMaxIDBetweenCClassTest(ClassC, ClassD); //没有发生对象拷贝的行为 pClassIDMax = ClassTmp.GetMaxIDBetweenCClassTest(&ClassC, pClassA); pClassIDMax = ClassTmp.GetMaxIDBetweenCClassTest(pClassA, pClassB); /** * 下面的2句实验函数传进了二级指针和指针的引用 * 实验结论: * 只要传的是指针, 二级指针, 指针的引用, 都不会发生对象的拷贝, 也不会产生临时对象 * 传 xx*& 写代码时要简洁清晰一些 * * 遗留问题: * CClassTest::CClassTest(const CClassTest * prhs)这个自己推测的拷贝构造函数 * 从来没看调用进过这个函数, 莫非这是传指针不会进行拷贝构造临时对象的一个辅助证明? */ pClassA->CopyBufIflhsHasEnoughLength(&pClassB);//传的是CClassTest** pClassA->CopyBufIflhsHasEnoughLength(pClassB);//传的是CClassTest*& ClassC.Dump(); ClassD.Dump(); delete pClassB; pClassB = NULL; delete pClassA; pClassA = NULL; } void nFnTestPRef() { }

    // ClassTest.h: interface for the CClassTest class. // // #if !defined(AFX_CLASSTEST_H__11BC6892_54CD_4F31_9E19_0B37E0A43E8F__INCLUDED_) #define AFX_CLASSTEST_H__11BC6892_54CD_4F31_9E19_0B37E0A43E8F__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 //#define G_USE_OPERATOR_EQU_CASE_1 class CClassTest { public: CClassTest();/**< 默认构造函数 */ CClassTest(const CClassTest & rhs);/**< 拷贝构造函数 */ CClassTest(const CClassTest * prhs);/**< 拷贝构造函数 */ #ifdef G_USE_OPERATOR_EQU_CASE_1 /** ClassC = *pClassA;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) ClassD = ClassC;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) *pClassB = *pClassA;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) */ CClassTest& operator= (CClassTest& rhs); /** *pClassB = pClassA;//进入 CClassTest* CClassTest::operator= (CClassTest* prhs) ClassD = pClassB;//进入 CClassTest* CClassTest::operator= (CClassTest* prhs) */ CClassTest& operator= (CClassTest* prhs); #else /** ClassC = *pClassA;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) ClassD = ClassC;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) *pClassB = *pClassA;//进入 CClassTest& CClassTest::operator= (CClassTest& rhs) */ CClassTest* operator= (CClassTest& rhs); /** *pClassB = pClassA;//进入 CClassTest* CClassTest::operator= (CClassTest* prhs) ClassD = pClassB;//进入 CClassTest* CClassTest::operator= (CClassTest* prhs) */ CClassTest* operator= (CClassTest* prhs); #endif virtual ~CClassTest(); void Dump(LPCSTR csTip = "CClassTest"); void SetBuf(PTCHAR pcMsg); PTCHAR GetBuf() {return m_pBuf;} void SetID(DWORD dwID); DWORD GetID() {return m_dwID;} CClassTest * GetMaxIDBetweenCClassTest(CClassTest lhs, CClassTest rhs); // CClassTest * GetMaxIDBetweenCClassTest(CClassTest &lhs, CClassTest &rhs); CClassTest * GetMaxIDBetweenCClassTest(CClassTest *lhs, CClassTest *rhs); BOOL CopyBufIflhsHasEnoughLength(CClassTest ** lhs); BOOL CopyBufIflhsHasEnoughLength(CClassTest *& lhs); private: void DataInit(); void DataUnInit(); private: PCHAR m_pBuf; DWORD m_dwID; }; #endif // !defined(AFX_CLASSTEST_H__11BC6892_54CD_4F31_9E19_0B37E0A43E8F__INCLUDED_)

    // ClassTest.cpp: implementation of the CClassTest class. // // #include "stdafx.h" #include "DiffPpPRef.h" #include "ClassTest.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif // // Construction/Destruction // CClassTest::CClassTest() { CString csMsg; csMsg.Format(">> this=[%p]CClassTest::CClassTest()/n", this); OutputDebugString(csMsg); DataInit(); } CClassTest::CClassTest(const CClassTest & rhs) { /*传值拷贝时进入的构造函数, 函数形参是类对象时产生临时对象, 进入此拷贝构造函数 * 不进入默认拷贝构造函数 */ CString csMsg; csMsg.Format(">> this=[%p]CClassTest::CClassTest(const CClassTest & rhs)/n", this); OutputDebugString(csMsg); if(this == &rhs) return; DataInit();//所以这里要执行以下数据初始化 } CClassTest::CClassTest(const CClassTest * prhs) { /*传指针拷贝时进入的构造函数, 函数形参是类指针时产生临时对象, 进入此拷贝构造函数 * 不进入默认拷贝构造函数 * * 没看见进过这个拷贝构造函数!!! */ CString csMsg; csMsg.Format(">> this=[%p]CClassTest::CClassTest(const CClassTest * prhs)/n", this); OutputDebugString(csMsg); if(this == prhs) return; DataInit();//所以这里要执行以下数据初始化 } CClassTest * CClassTest::GetMaxIDBetweenCClassTest(CClassTest lhs, CClassTest rhs) { return (lhs.GetID() > rhs.GetID()) ? &lhs : &rhs; } // CClassTest * CClassTest::GetMaxIDBetweenCClassTest(CClassTest &lhs, CClassTest &rhs) // { // return (lhs.GetID() > rhs.GetID()) ? &lhs : &rhs; // } CClassTest * CClassTest::GetMaxIDBetweenCClassTest(CClassTest *lhs, CClassTest *rhs) { return (lhs->GetID() > rhs->GetID()) ? lhs : rhs; } #ifdef G_USE_OPERATOR_EQU_CASE_1 CClassTest& CClassTest::operator= (CClassTest& rhs) { CString csMsg; csMsg.Format(">> this=[%p]CClassTest& CClassTest::operator= (CClassTest& rhs)/n", this); OutputDebugString(csMsg); if(this == &rhs) return *this; return *this; } CClassTest& CClassTest::operator= (CClassTest* prhs) { CString csMsg; csMsg.Format(">> this=[%p]CClassTest& CClassTest::operator= (CClassTest* prhs)/n", this); OutputDebugString(csMsg); if(this == prhs) return *this; return *this; } #else CClassTest* CClassTest::operator= (CClassTest& rhs) { CString csMsg; csMsg.Format(">> this=[%p]CClassTest& CClassTest::operator= (CClassTest& rhs)/n", this); OutputDebugString(csMsg); if(this == &rhs) return this; return this; } CClassTest* CClassTest::operator= (CClassTest* prhs) { CString csMsg; csMsg.Format(">> this=[%p]CClassTest& CClassTest::operator= (CClassTest* prhs)/n", this); OutputDebugString(csMsg); if(this == prhs) return this; return this; } #endif CClassTest::~CClassTest() { CString csMsg; csMsg.Format(">> this=[%p]CClassTest::~CClassTest()/n", this); OutputDebugString(csMsg); DataUnInit(); } void CClassTest::DataInit() { OutputDebugString(">> void CClassTest::DataInit()/n"); m_pBuf = NULL; m_dwID = 0; } void CClassTest::DataUnInit() { OutputDebugString("void CClassTest::DataUnInit()/n"); if(m_pBuf) { delete m_pBuf; m_pBuf = NULL; } m_dwID = 0; } void CClassTest::SetBuf(PTCHAR pcMsg) { OutputDebugString("void CClassTest::SetBuf(PTCHAR pcMsg)/n"); if(m_pBuf) { delete m_pBuf; m_pBuf = NULL; } if(pcMsg) { m_pBuf = new TCHAR[strlen(pcMsg) + 1]; *(m_pBuf + strlen(pcMsg)) = '/0'; strcpy(m_pBuf, pcMsg); } } void CClassTest::SetID(DWORD dwID) { OutputDebugString("void CClassTest::SetID(DWORD dwID)/n"); m_dwID = dwID; } void CClassTest::Dump(LPCSTR csTip) { CString csMsg; csMsg.Format(">> this=[%p]void CClassTest::Dump(LPCSTR csTip)/n", this); OutputDebugString(csMsg); csMsg.Format("----------------------------------------/n"); OutputDebugString(csMsg); csMsg.Format("CClassTest[%s] Infomation:/n", csTip); OutputDebugString(csMsg); csMsg.Format("Addr[%p]/n", this); OutputDebugString(csMsg); csMsg.Format("m_pBuf => Addr[%p], Value[%s]/n", &m_pBuf, m_pBuf); OutputDebugString(csMsg); csMsg.Format("m_dwID => Addr[%p], Value[%d]/n", &m_dwID, m_dwID); OutputDebugString(csMsg); csMsg.Format("----------------------------------------/n"); OutputDebugString(csMsg); } BOOL CClassTest::CopyBufIflhsHasEnoughLength(CClassTest ** lhs) { CString csMsg; csMsg.Format(">> this=[%p]BOOL CClassTest::CopyBufIflhsHasEnoughLength(CClassTest ** lhs)/n", this); OutputDebugString(csMsg); PTCHAR pBuflhs = (*lhs)->GetBuf(); if(!pBuflhs) return FALSE; int nLen = strlen(pBuflhs); int nLenMe = strlen(GetBuf()); if(nLen > nLenMe) { strcpy(pBuflhs, GetBuf()); } return TRUE; } BOOL CClassTest::CopyBufIflhsHasEnoughLength(CClassTest *& lhs) { CString csMsg; csMsg.Format(">> this=[%p]BOOL CClassTest::CopyBufIflhsHasEnoughLength(CClassTest *& lhs)/n", this); OutputDebugString(csMsg); PTCHAR pBuflhs = lhs->GetBuf(); if(!pBuflhs) return FALSE; int nLen = strlen(pBuflhs); int nLenMe = strlen(GetBuf()); if(nLen > nLenMe) { strcpy(lhs->GetBuf(), GetBuf()); //直接改变lhs的值, 出去后可以看到lhs的值已经变了 //和操作二级指针效果相同, 而且书写简单 } return TRUE; }

    实现表明, 拷贝构造函数写成下面的两种形式均可 CClassTest& operator= (CClassTest& rhs); CClassTest* operator= (CClassTest& rhs);

     

    最新回复(0)