[英]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_ptr
或shared_ptr
類的智能指針)。
對於這兩種情況,都有一系列習語和模式,但是第一點是要了解您要針對的模型並表現出連貫的行為。
但是您無論如何都不會獲得一件事:C ++永遠不會像Java。 因此,請勿嘗試模仿它。 通過值或指針(通過引用並不會改變很多),您必須以另一種方式思考。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.