簡體   English   中英

用C ++返回一個類

[英]Returning a class in C++

在Java中,所有類都是真正的引用,我這樣做:

Car getCar(int mileage)
{
  Car car = new Car();

  car.setMileage(mileage);
  return car;
}

在C ++中,我該怎么做? 我可以參考一下:

void getCar(int mileage, Car& car)
{
  car.setMileage(mileage);
  return true;
}

或者,我可以創建一個新對象:

Car* getCar(int mileage)
{
  Car* car = new Car;

  car.setMileage(mileage);
  return car;
}

但隨后,呼叫者還負責刪除car

我不想返回一個指針。 我要退車:

Car getCar(int mileage)
{
  Car car;

  car.setMileage(mileage);
  return car;
}

但是,當然, car是一個局部變量,函數完成后將被刪除。

通常,這樣做的“標准”方式是什么? 最好的方法是什么,為什么?

您的最后一段代碼很好-您返回的是局部變量的值,而不是局部變量本身,所以發生的事情是(至少在理論上)該值將從局部變量復制到調用者的任何位置分配它。

這基本上和我有類似的東西一樣:

int f() { 
    int x = 0; 
    return x;
}

同樣,我們返回一個值。 該值恰好來自局部變量,但我們仍在返回值,而不是變量。

就“至少在理論上”部分而言,大多數編譯器都可以對此進行優化,因此根本不會進行任何復制。 有一些特殊的規則允許編譯器跳過復制,即使復制會在復制發生時產生您希望看到的外部可見副作用(例如,如果您編寫的復制構造函數在復制時打印出一些內容)復制發生了)。

最后一個示例是返回對象的正確且慣用的方式:

Car getCar(int mileage)
{
  Car car;

  car.setMileage(mileage);
  return car;
}

是的, car將在函數末尾刪除,但不會在復制到返回的對象之前刪除。 您可以像這樣調用此函數:

{
    Car myCar;
    myCar = getCar(42);
}

getCar本地的car被復制到調用環境的myCar


您不能也不能做的是返回對局部變量的引用或指針。 這是錯誤的:

 Car& getCar(int mileage) { Car car; return car; } 

這也是錯誤的:

 Car* getCar(int mileage) { Car car; return &car; } 

在每種情況下,都允許調用函數訪問不再存在的對象

您不得返回指向本地的指針或引用。 您可以返回本地副本。

Car getCar(int mileage) {   Car car = new Car();    car.setMileage(mileage);   return car; }

在C ++中,我該怎么做? 我可以參考一下:

void getCar(int mileage, Car& car) {   car.setMileage(mileage);   return true; }

是的-沒關系,盡管您不能為void函數返回任何內容。

或者,我可以創建一個新對象:

Car* getCar(int mileage) {   Car* car = new Car;    car.setMileage(mileage);   return car; }

但隨后,呼叫者還負責刪除汽車。

是的,但是您可以使用智能指針來使其更可靠,更方便。

我不想返回一個指針。 我要退車:

Car getCar(int mileage) {   Car car;    car.setMileage(mileage);   return car; }

但是,當然,car是一個局部變量,函數完成后將被刪除。

不是真的-這很完美-car對象是通過value返回 ,這意味着調用者可以在堆棧中使用它來在表達式中使用,包括用作在其他地方復制的源。

通常,這樣做的“標准”方式是什么? 最好的方法是什么,為什么?

通常,上面的最后一個版本是“標准”方式-通常效率很高(通常在優化構建時是最佳選擇),避免出現混亂的指針,並且直觀而簡單。 當然,從可以做到這一點的C ++到需要在各處添加new變量的Java都是痛苦的。

要很好理解的重要區別是,在Java對象中,引用是通過引用並通過其地址來標識的。

在C ++中,它們是“值”(例如int ),並且...由它們的地址標識:-((這是規范將對象稱為)的方式

無論成語怎么說,您都必須做出決定:對您來說重要的是值還是地址?

具有相同name值的兩個Person代表相同的(在現實世界中) ,或者兩個真實單詞的諧音 -s? 多態性在您的上下文中有多重要? (是否存在由不同的Person派生的多種“ person -s”)?

這不是“成語”所說的。 這是您必須建立的約定。

如果要使用值,請按值返回(注意:在大多數情況下,編譯器會忽略“返回時復制”,因此它不是性能限制器),但是卻忘記了多態性。 但是,如果您的對象包含一些資源,請確保它們也遵循“按值”范式,否則請准備重寫構造函數,析構函數,復制構造函數,移動構造函數和分配以正確處理資源所有權。 或者...使用按值資源管理器將它們包裝起來(智能指針可以做到這一點)。

如果您要使用地址,並且需要多態性,那么要准備在堆上分配對象,使用指針並正確管理分配/釋放(最終借助諸如unique_ptrshared_ptr類的智能指針)。

對於這兩種情況,都有一系列習語和模式,但是第一點是要了解您要針對的模型並表現出連貫的行為。

但是您無論如何都不會獲得一件事:C ++永遠不會像Java。 因此,請勿嘗試模仿它。 通過值或指針(通過引用並不會改變很多),您必須以另一種方式思考。

暫無
暫無

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

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