乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      引用參數(shù)與引用返回值,臨時(shí)對(duì)象

       mediatv 2014-04-25


       經(jīng)??吹竭@樣的聲明:T& func(T& t),這種聲明和T func(T t)有什么區(qū)別?書上的解釋是為了提高效率,究竟是如何提高效率的呢??jī)?nèi)部執(zhí)行了什么操作?本文通過8個(gè)小例子對(duì)引用參數(shù)和引用返回進(jìn)行了一次徹底的排查。
          首先看一下在類的成員函數(shù)中的引用參數(shù)和引用返回值:

      類定義class A
      {
           public:
            int x;

            A(){}//構(gòu)造函數(shù)
            A(const A& other)//拷貝構(gòu)造函數(shù)
            {
                  this->x = other.x;
                  cout << "Copy" << endl;
            }

            ~A(){}//析構(gòu)函數(shù)

            A& operator=(const A& other)//賦值函數(shù)
            {
                  this->x = other.x;
                  cout << "Assign" << endl;
                  return *this;
            }

            void func1(A a)
            {

            }

            void func2(A& a)
            {

            }

            A func3()
            {
                  return *this;
            }
       
            A& func4()
            {
                  return *this;
            }
      };

          這個(gè)類很簡(jiǎn)單,只有一個(gè)成員變量x,并且定義了默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、析構(gòu)函數(shù)和賦值函數(shù)。為了能夠更清楚地看到哪個(gè)拷貝構(gòu)造函數(shù)與賦值函數(shù)是否被調(diào)用,在這兩個(gè)函數(shù)中添加了一些輸出信息。
          類中還定義了四個(gè)成員函數(shù),下面分別分析這四個(gè)函數(shù)的執(zhí)行情況。
          (1) 在main()函數(shù)中調(diào)用func1():

      調(diào)用func1()int main()
      {
            A a1, a2;
            a2.func1(a1);

            return 0;
      }

      func1()輸出結(jié)果Copy
          為什么會(huì)有這樣的輸出結(jié)果呢?這是由于func1()中傳遞的是值參數(shù),因此在執(zhí)行函數(shù)體之前會(huì)先產(chǎn)生一個(gè)臨時(shí)對(duì)象,然后調(diào)用類的拷貝構(gòu)造函數(shù)初始化這個(gè)臨時(shí)對(duì)象,從而輸出了"Copy"。在函數(shù)內(nèi)部操作的是這個(gè)臨時(shí)對(duì)象,對(duì)臨時(shí)對(duì)象所做的任何修改不會(huì)反映到函數(shù)的實(shí)參上。

          (2) 在main()函數(shù)中調(diào)用func2()以與func1()對(duì)比:

      調(diào)用func2()int main()
      {
            A a1, a2;
            a2.func2(a1);

            return 0;
      }

      func2()輸出結(jié)果

          結(jié)果什么也沒有輸出。
          這是由于傳入的是一個(gè)引用參數(shù),因此在函數(shù)內(nèi)部不需要產(chǎn)生一個(gè)臨時(shí)對(duì)象來保存對(duì)象信息,
      因此不會(huì)調(diào)用拷貝構(gòu)造函數(shù)。這就是引用參數(shù)的作用,減少一次對(duì)象的拷貝,提高了函數(shù)的效率。

          (3) 在main()函數(shù)中調(diào)用func3():

      調(diào)用func3()int main()
      {
            A a1, a2;
            a2 = a1.func3();

            return 0;
      }

      func3()輸出結(jié)果Copy
      Assign

          為什么會(huì)輸出"Copy"呢?這是因?yàn)楹瘮?shù)采用的是值返回,因此為了保存返回值,需要先創(chuàng)建一個(gè)臨時(shí)對(duì)象,然后調(diào)用類的拷貝構(gòu)造函數(shù)將*this的內(nèi)容拷貝到這個(gè)臨時(shí)對(duì)象中,再將臨時(shí)對(duì)象返回。最后通過賦值函數(shù)將該臨時(shí)對(duì)象的內(nèi)容賦值給新對(duì)象。

          (4) 在main()函數(shù)中調(diào)用func4()以與func3()對(duì)比:

      調(diào)用func4()int main()
      {
       A a1, a2;
       a2 = a1.func4();

       return 0;
      }

      func4()輸出結(jié)果Assign

          只調(diào)用了賦值函數(shù),這是引用函數(shù)采用的是引用返回,因此直接返回對(duì)象自身的引用*this,不需要?jiǎng)?chuàng)建臨時(shí)對(duì)象來保存對(duì)象信息,因此不會(huì)調(diào)用拷貝構(gòu)造函數(shù)。最后通過賦值函數(shù)直接將對(duì)象本身的內(nèi)容賦值給新對(duì)象。這就是引用返回值的作用,減少了一次對(duì)象的拷貝,提高了函數(shù)的效率。

          總結(jié)一下:在類的成員函數(shù)中,使用引用參數(shù)和引用返回值都不需要產(chǎn)生臨時(shí)對(duì)象,減少了一次對(duì)象的拷貝,提高了函數(shù)的效率。

          那么,如果將參數(shù)作為返回值返回,并且用引用接收返回值將會(huì)產(chǎn)生什么效果呢?下面定義四個(gè)全局函數(shù):

      全局函數(shù)A& func5(A& a)
      {
            return a;
      }

      A& func6(A a)
      {
            return a;
      }

      A func7(A& a)
      {
            return a;
      }

      A func8(A a)
      {
            return a;
      }

          (5) 在main()函數(shù)中調(diào)用func5():

      調(diào)用func5()int main()
      {
            A a1;
            a1.x = 1;
            A& a2 = func5(a1);
            a1.x++;
       
            cout << a1.x << endl;
            cout << a2.x << endl;

            return 0;
      }

      func5()輸出結(jié)果2
      2

          func5()采用了引用參數(shù),并且以引用返回值的方式返回了該參數(shù),因此a2是a1的一個(gè)引用,對(duì)a1的任何改變都會(huì)反映到a2上,所以a1、a2的成員變量x的值相同。

          (6) 在main()函數(shù)中調(diào)用func6():

      調(diào)用func6()int main()
      {
            A a1;
            a1.x = 1;
            A& a2 = func6(a1);
            a1.x++;
       
            cout << a1.x << endl;
            cout << a2.x << endl;
       
            return 0;
      }

      編譯的時(shí)候會(huì)報(bào)一個(gè)警告:

      警告warning C4172: returning address of local variable or temporary

      func6()輸出結(jié)果Copy
      2
      4198610

          警告的意思就是返回了一個(gè)局部變量的引用,這種用法實(shí)際上是錯(cuò)誤的。局部變量在函數(shù)返回前就會(huì)被釋放,因此實(shí)際上a2引用到的一塊不可知的內(nèi)存,這從輸出的a2.x的值"4198610"也可以看出來。至于輸出"Copy",是因?yàn)椴捎玫氖侵祬?shù),上面已經(jīng)討論過,這里不再贅述。

          (7) 在main()函數(shù)中調(diào)用func7():

      調(diào)用func7()int main()
      {
            A a1;
            a1.x = 1;
            const A& a2 = func7(a1);
            a1.x++;
       
            cout << a1.x << endl;
            cout << a2.x << endl;

            return 0;
      }

      func7()輸出結(jié)果Copy
      2
      1

          這是一種比較特殊的用法,由于func7()采用的是值返回,因此在函數(shù)返回前將會(huì)產(chǎn)生一個(gè)臨時(shí)對(duì)象,并執(zhí)行一次拷貝構(gòu)造函數(shù)。這樣相當(dāng)于a2引用了一個(gè)臨時(shí)對(duì)象。前面曾經(jīng)說過,臨時(shí)對(duì)象將會(huì)在函數(shù)返回前被釋放,但是為什么這里輸出的結(jié)果是正常的呢?這是一種特殊情況,C++規(guī)定,如果有臨時(shí)對(duì)象有一個(gè)引用,那么這個(gè)臨時(shí)對(duì)象的生存期將延長(zhǎng)到和這個(gè)引用相同。樣就可以解釋上面的輸出結(jié)果了:a2引用了一個(gè)臨時(shí)對(duì)象,而不是引用了a1,因此a1的任何改變不會(huì)影響到a2。

          注意:在VC編譯環(huán)境下,const A& a2 = func7(a1);這行語(yǔ)句前面可以不加"const",但是在g++或者其他版本的編譯器中不加"const"將會(huì)產(chǎn)生編譯錯(cuò)誤。加上"const" 更加符合C++標(biāo)準(zhǔn)的規(guī)定,因?yàn)榕R時(shí)對(duì)象不可見,不允許通過該引用來改變臨時(shí)對(duì)象的內(nèi)容。

          (8) 在main()函數(shù)中調(diào)用func8():

      調(diào)用func8()int main()
      {
            A a1;
            a1.x = 1;
            const A& a2 = func8(a1);
            a1.x++;
       
            cout << a1.x << endl;
            cout << a2.x << endl;
       
            return 0;
      }

      func8()輸出結(jié)果Copy
      Copy
      2
      1

          通過以上的分析,對(duì)這個(gè)輸出結(jié)果也就很好理解了:由于采用的是值參數(shù),因此在函數(shù)體執(zhí)行前會(huì)調(diào)用一次拷貝構(gòu)造函數(shù);采用的是值返回值,因此在函數(shù)返回前又會(huì)調(diào)用一次拷貝構(gòu)造函數(shù),這就是前兩個(gè)"Copy"的由來。另外,a2引用的是一個(gè)臨時(shí)對(duì)象,而不是引用了a1,因此a1的任何改變不會(huì)影響到a2。

          總結(jié)一下:
          如果使用引用接收引用返回值,則返回的引用必須具有較長(zhǎng)的生存期,不可以引用局部變量。
          如果使用引用接收值返回值,則引用了一個(gè)臨時(shí)對(duì)象,該對(duì)象的生存期將延長(zhǎng)到和這個(gè)引用相
      同。


      原文出處:http://www.cnblogs.com/bigshow/archive/2008/11/10/1330514.html   

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多