對於這種特殊情況,您可以充分利用現今編譯器足夠聰明的優勢。該優化被稱爲,名爲return value optimization(NRVO),因此可以返回這樣的「大」對象。編譯器可以看到這樣的機會(特別是在代碼片段那樣簡單的情況下)並生成二進制文件,以便不會創建副本。
您還可以返回無名臨時對象:
Object f()
{
return Object();
}
這將調用(未命名)返回值優化(RVO)在幾乎所有的現代C++編譯器。事實上,即使所有的優化都被關閉,Visual C++也實現了這種特殊的優化。
這些種類的優化特別通過C++標準允許的:
ISO 14882:2003 C++標準,§12.8段。 15: 複製類對象
當滿足特定條件時,一個 實現允許省略類對象的 拷貝構造, 即使複製構造和/或 析構函數爲對象具有側 效果。在這種情況下, 執行將源和省略複製操作的 目標 作爲簡單的 兩種不同的方式指代相同的對象,並且 破壞該對象的發生 當兩個 對象時代的後面在沒有優化的情況下會被銷燬 。拷貝操作的這個elison 在 下列情況下才允許(其可以是 組合以消除多個 份):在與類terturn類型的功能的return
聲明
- , 當表達式是與 相同CV-不合格類型作爲 函數返回類型的 非易失性自動對象的名稱,拷貝 操作可以通過 構造自動對象 直接進入函數的返回被省略值
- 當尚未結合至參考 臨時類對象將被複制到一個類對象與 相同CV-unqualitied型,複製 操作可以通過 直接構建臨時對象 可以省略進入 省略副本的目標。
一般來說,編譯器會一直嘗試實施NRVO和/或視網膜靜脈阻塞,但它可能無法在某些情況下這樣做,就像多個返回路徑。不過,這是一個非常有用的優化,你不應該害怕使用它。
如果有疑問,可以隨時通過插入「調試語句」測試你的編譯器,並看到自己:
class Foo
{
public:
Foo() { ::printf("default constructor\n"); }
// "Rule of 3" for copyable objects
~Foo() { ::printf("destructor\n"); }
Foo(const Foo&) { ::printf("copy constructor\n"); }
Foo& operator=(const Foo&) { ::printf("copy assignment\n"); }
};
Foo getFoo()
{
return Foo();
}
int main()
{
Foo f = getFoo();
}
如果返回的對象並不意味着可拷貝,或者(N)RVO失敗(這可能是不太可能發生),那麼你可以嘗試返回一個代理對象:
struct ObjectProxy
{
private:
ObjectProxy() {}
friend class Object; // Allow Object class to grab the resource.
friend ObjectProxy f(); // Only f() can create instances of this class.
};
class Object
{
public:
Object() { ::printf("default constructor\n"); }
~Object() { ::printf("destructor\n"); }
// copy functions undefined to prevent copies
Object(const Object&);
Object& operator=(const Object&);
// but we can accept a proxy
Object(const ObjectProxy&)
{
::printf("proxy constructor\n");
// Grab resource from the ObjectProxy.
}
};
ObjectProxy f()
{
// Acquire large/complex resource like files
// and store a reference to it in ObjectProxy.
return ObjectProxy();
}
int main()
{
Object o = f();
}
當然,這是不完全明顯,將需要使適當的文件(至少一個關於它的評論)。
您還可以將某種智能指針(如std::auto_ptr
或boost::shared_ptr
或類似的東西)返回給免費商店中分配的對象。如果您需要返回派生類型的實例,則需要此操作:
class Base {};
class Derived : public Base {};
// or boost::shared_ptr or any other smart pointer
std::auto_ptr<Base> f()
{
return std::auto_ptr<Base>(new Derived);
}
技術上是的。但是對於這樣一個簡單的函數,編譯器會優化拷貝。構建代碼在構造函數/複製構造函數和析構函數中放置打印語句,然後在不進行優化並完全優化的情況下構建代碼,並查看執行了多少個打印語句。 – 2011-01-26 19:38:37
那麼,如果這是C,那麼這只是一個對malloc的調用。如果它是C++,那麼你會新的對象。大概你的函數在返回之前對對象做了一些事情,否則它就沒有任何用處。你爲什麼把它標記爲C和C++?他們是不同的。 – 2011-01-26 19:39:13
c和C++因爲它可能是一個結構體或一個類。所以這種情況可能會出現在兩種語言中 – Andrew 2011-01-26 19:41:51