关闭

类对象的“传值”与“传引用”

标签: funclass
1043人阅读 评论(0) 收藏 举报
分类:

   "传值"就是通过值来传递一个对象,这个过程需要拷贝构造函数来进行。而"传引用"实质上就是一种指针传递。两种传递方式在使用上存在效率问题和"切割"问题。

 

   1、效率

   而前所述,"传值"需要调用拷贝构造函数。例如:

   class CTest
   {
   public:
       CTest()
       {
           cout << "CTest::CTest()" << endl;
       }

       CTest(const CTest& ref)
       {
           cout << "CTest::CTest(const CTest& ref)" << endl;
       }

       ~CTest()
       {
           cout << "CTest::~CTest()" << endl;
       }

       CTest fun(CTest obj)
       {
           return obj;
       }
   };

 

   void main()
   {
       CTest Obj, obj1;

       CTest obj2 = obj.fun(obj1);
   }

   上述代码的输出结果是:

   CTest::CTest()

   CTest::CTest()

   CTest::CTest(const CTest& ref)

   CTest::CTest(const CTest& ref)

   CTest::~CTest()

   CTest::~CTest()

   CTest::~CTest()

   CTest::~CTest()

   在调用fun()成员函数时,传入实参调用一次拷贝构造函数,返回值调用一次拷贝构造函数。也就是说:调用一次fun()成员函数,需要调用两次拷贝构造函数和两次析构函数。如此昂贵的开销不得不让人有所警惕。

   定义一个对象的引用就是给对象起个别名,无需调用拷贝构造函数。因而,将fun()成员函数的形参和返回值改为"传引用",能避免调用拷贝构造函数和析构函数。这社会,能节省开销就要节省开销。

   *注:在上述例子中,将返回值改为"传引用"只是为了说明问题,其实返回局部对象的引用,其后果是难以预测的。

 

   2、切割问题

   当一个派生类的对象作为基类对象被传递时,它(派生类对象)的作为派生类所具有的行为特性会被“切割”掉,从而变成了一个简单的基类对象。例如:

   class CBase

   {

   public:

      virtual void Display()

      {

          cout << "CBase::Display()" << endl;

      }

   };

 

   class CDerive : public CBase

   {

   public:

       virtual void Display()

       {

           cout << "CDerive::Display()" << endl;

       }

   };

 

   void fun(CBase ObjCBase)

   {

       ObjCBase.Diaplay();

   }

 

   这时,如果执行下面语句:

   CDerive ObjCDerive;

   fun(ObjCDerive);

   很抱歉,这时执行的是CBase::Display()。这就是切割问题。其实也不难理解:fun()申请的是CBase对象的空间BUF1,这时跑来的却是CDerive对象的空间BUF2,BUF1可装不下BUF2,不好意思,BUF2中除BUF1以外的空间必须切割掉。这种切割问题很明显违反了程序员的意图。

   如果将fun()的形参改为"传引用",问题就回到多态性上了。"传引用"实质就是一种地址传递,这时候基类的指针指向派生类,因而调用的虚函数就是派生类的虚函数。这时程序员的意图得到了表达。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:16849次
    • 积分:370
    • 等级:
    • 排名:千里之外
    • 原创:22篇
    • 转载:2篇
    • 译文:0篇
    • 评论:0条