[英]Should I return reference to heap object or return value?
我有這兩個簡單的功能。 我認為func1
是一個很好的解決方案,因為你通過引用傳遞一個對象。 我的教科書給了func2
作為最佳解決方案的答案。 這只是因為你沒有解除heapstr
? 如果我在main中聲明了heapstr
然后將它傳遞給函數,那么我之后能夠刪除它會怎么樣?
#include <iostream>
using namespace std;
string& func1(const string &str) {
string* heapstr=new string();
for (int i = 0; i < str.size(); ++i) {
*heapstr += str[i];
}
return *heapstr;
}
string func2(const string &str) {
string heapstr;
for (int i = 0; i < str.size(); ++i) {
heapstr += str[i];
}
return heapstr;
}
int main() {
cout << func1("aaa") << endl;
cout << func2("aaa") << endl;
}
我應該返回堆對象的引用還是返回值?
按價值返回。
有很多原因,但沒有一個與性能有關,因為編譯器在優化方面已經足夠好了,即使不是,大多數程序都受I / O限制,即等待數據的時間從文件或網絡套接字中獲取所有性能,而不是CPU操作本身所花費的時間。
例如,參見Herb Sutter和Bjarne Stroustrup撰寫的“C ++核心指南”,其中“按價值返回容器(依靠移動或復制省略效率)”部分說 :
原因
簡化代碼並消除對顯式內存管理的需求。
至於你的兩個功能......
我的教科書給了
func2
作為最佳解決方案的答案。 這只是因為你沒有解除heapstr
?
內存泄漏是其中一個問題。 但重點是,按值返回更簡單,更不容易出錯。 這都是關於正確性 ,而不是速度。 如果你只能返回一個int
,你就不會返回一個int*
,不是嗎?
如果我在
main
聲明了heapstr
然后將它傳遞給函數,那么我之后能夠刪除它會怎么樣?
您將在代碼中引入許多內存泄漏,崩潰和未定義行為的可能性。 它會變得更長,更難寫,更難閱讀,更難維護,更難調試,更難以在代碼審查中證明其合理性。 作為回報,你絕對不會獲得任何收益。
教科書是正確的。 (令人震驚。)
Func1在各個方面都有缺陷,它與func2不同。 它從堆中分配一個對象,而不考慮該對象的刪除方式。 然后它返回對新對象的引用,隱藏可能已經用於刪除它的指針。 沒有效率增益,事實上Func1可能有點慢。 在任何情況下,請背誦我:“避免早期優化。”
自標准模板庫出現以來,許多月前,使用operator new幾乎都不是最佳選擇。 我最后一次使用operator new是ca. 2003年,我將指針包裝在我們現在所知的unique_ptr中。 在使用operator new之前,請閱讀所有有關智能指針和RAII的信息。
由於這是教科書的例子,你應該考慮它的上下文以及它想要准確顯示的內容(它的目標是在你或使用安全的編程模式時最小化內存使用量?!)。 但有兩個暗示
new
運算符分配內存時, 必須使用delete
取消分配。 代碼在func1
處有heapstr
內存泄漏。 PS:我沒有C ++ 17,但它也優化了以下內容。 有關更多詳細信息,請閱讀@BoPersson評論。
PS:堆棧分配更快,但在您的示例中,您在func2返回時有一個復制操作。 在你的例子中,@ Jive Dadson說由於編譯器優化沒有區別,但在一般情況下,假設下面的代碼
#include <iostream>
#include <string>
using namespace std;
string& func1(const string &str) {
string* heapstr = new string();
cout << "func1 " << heapstr << endl;
for (int i = 0; i < str.size(); ++i) {
*heapstr += str[i];
}
return *heapstr;
}
string func2(const string &str) {
string heapstr;
for (int i = 0; i < str.size(); ++i) {
heapstr += str[i];
}
cout << &heapstr << endl;
return heapstr;
}
int main() {
string a = func1("aaa");
string b = func2("aaa");
cout << "main " << a << endl;
}
PS :(正如@Jive Dadson所說,你的例子沒有區別,但在我的例子中)如果我們將性能定義為運行時,可能是func1。 此外,如果我們將性能定義為內存使用量,則為func1。 如果我們將性能定義為良好的編程模式,則為func2。 完全func2是更優選的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.