簡體   English   中英

什么時候在C ++中返回指針,標量和引用?

[英]When to return a pointer, scalar and reference in C++?

我正在從Java遷移到C ++,並對語言的靈活性有些困惑。 一點是,有三種存儲對象的方式:指針,引用和標量(如果我正確理解,則存儲對象本身)。

我傾向於在可能的地方使用引用,因為它與Java越接近越好。 在某些情況下,例如,派生屬性的獲取程序,這是不可能的:

MyType &MyClass::getSomeAttribute() {
    MyType t;
    return t;
}

這不會編譯,因為t僅存在於getSomeAttribute()的范圍內,並且如果我返回對其的引用,則在客戶端可以使用它之前它不會指向任何地方。

因此,我有兩個選擇:

  1. 返回一個指針
  2. 返回標量

返回一個指針看起來像這樣:

MyType *MyClass::getSomeAttribute() {
    MyType *t = new MyType;
    return t;
}

這是可行的,但是客戶端必須檢查此指針是否為NULL才能真正確定,這對於引用不是必需的。 另一個問題是調用者必須確保將t釋放,如果可以避免的話,我寧願不處理它。

另一種方法是返回對象本身(標量):

MyType MyClass::getSomeAttribute() {
    MyType t;
    return t;
}

這非常簡單,正是我在這種情況下想要的:感覺像是一個引用,不能為null。 如果該對象超出了客戶端代碼的范圍,則將其刪除。 很方便。 但是,我很少看到有人這樣做,這是有原因的嗎? 如果我返回標量而不是指針或引用,是否會有某種性能問題?

解決此問題的最常見/最優雅的方法是什么?

按值返回。 編譯器可以優化副本,因此最終結果就是您想要的。 創建一個對象,並將其返回給調用者。

我認為您很少看到別人這樣做的原因是因為您正在查看錯誤的C ++代碼。 ;)大多數來自Java的人都對這樣做感到不自在,因此他們到處都是new 然后它們到處都是內存泄漏,必須檢查NULL以及可能引起的所有其他問題。 :)

值得指出的是,C ++引用與Java引用幾乎沒有共同之處。 Java中的引用與指針非常相似(可以重新定位,也可以將其設置為NULL)。 實際上,唯一真正的區別是指針也可以指向垃圾值(如果未初始化,或者指向超出范圍的對象),並且可以對指針進行指針算術運算。數組。 C ++引用是對象的別名。 Java引用的行為並非如此。

很簡單,盡可能避免使用new指針和動態分配。 請改用值,引用和自動分配的對象。 當然,您不能總是避免動態分配,但是這應該是最后的選擇,而不是第一選擇。

按值返回可能會導致性能下降,因為這意味着需要復制對象。 如果它是一個大對象(如列表),則該操作可能會非常昂貴。

但是現代編譯器非常擅長於避免這種情況的發生。 C ++標准明確聲明在某些情況下允許編譯器取消復制。 與您提供的示例代碼相關的特定實例稱為“返回值優化”。

就個人而言,當我返回成員變量時,我通過(通常為const)引用返回,並在需要動態分配某些內容時返回某種類型的智能指針對象(通常為::std::auto_ptr )。 否則,我將按價值返回。

我也經常有const引用參數,這在C ++中很常見。 這是傳遞參數並說“該功能不允許觸摸”的一種方式。 基本上是一個只讀參數。 但是,僅應將其用於比單個整數或指針更復雜的對象。

我認為Java的一大變化是const非常重要且經常使用。 學習了解它,並使其成為您的朋友。

我還認為Neil的答案是正確的,它指出盡可能避免動態分配是一個好主意。 您不應該過多地扭曲設計以使之實現,但是您絕對應該選擇不必進行設計的選擇。

按值返回是C ++中常見的做法。 但是,在傳遞對象時,將通過引用傳遞。

 main()
   {

       equity trader;

       isTraderAllowed(trader);

       ....
    }

    bool isTraderAllowed(const equity& trdobj)
    {
             ... // Perform your function routine here.
    }

上面是通過引用傳遞對象的簡單示例。 實際上,您將有一個名為isTraderAllowed的方法用於類權益,但是我向您展示了按引用傳遞的實際用法。

關於通過值或引用傳遞的一點:
考慮到優化,假設一個函數為inline ,如果其參數聲明為“ const DataType objectName”,則該DataType甚至可以是基元,也不會涉及任何對象副本; 如果將其參數聲明為“ const DataType&objectName”或“ DataType&objectName”,則DataType甚至可以是原語,也不會涉及地址獲取或指針。 在上述兩種情況下,輸入參數都直接在匯編代碼中使用。

關於參考的一點:
引用並不總是一個指針,例如,當您在函數主體中具有以下代碼時,該引用就不是指針:

int adad=5;
int & reference=adad;  

關於按值返回的一點:
正如某些人提到的,使用具有優化功能的良好編譯器,按任何類型的值返回都不會導致多余的副本。

關於按參考歸還的要點:
對於內聯函數和優化,按引用返回將不涉及地址獲取或指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM