2013-03-08 136 views
1

我正在通過Thinking in C++ - Bruce Eckel中的這個特定示例。我可以理解語句1(在評論中提到)和語句2,但很難理解在甚至沒有返回時語句3如果函數聲明和定義需要返回一個對象用於複製目的。現在在這裏發生了什麼?對於其他兩個語句(1和2)我可以推斷的是,因爲我們已經指定了類中的複製構造編譯器防止bitcopying,而是處理它通過我們的功能裏面傳遞的對象定義的拷貝構造函數以及函數返回的對象。就在函數結束之前,函數內的臨時對象被複製爲返回值,然後被銷燬。我對嗎?返回值(返回對象)忽略時會發生什麼?

#include <fstream> 
#include <string> 
using namespace std; 
ofstream out("HowMany2.out"); 
class HowMany2 { 
    string name; // Object identifier 
    static int objectCount; 
    public: 
    HowMany2(const string& id = "") : name(id) { 
     ++objectCount; 
     print("HowMany2()"); 
    } 
    ~HowMany2() { 
     --objectCount; 
     print("~HowMany2()"); 
    } 
    // The copy-constructor: 
    HowMany2(const HowMany2& h) : name(h.name) { 
     name += " copy"; 
     ++objectCount; 
     print("HowMany2(const HowMany2&)"); 
    } 
    void print(const string& msg = "") const { 
     if(msg.size() != 0) 
     out << msg << endl; 
     out << '\t' << name << ": "<< "objectCount = "<< objectCount << endl; 
    } 
}; 
int HowMany2::objectCount = 0; 
// Pass and return BY VALUE: 
HowMany2 f(HowMany2 x) { 
    x.print("x argument inside f()"); 
    out << "Returning from f()" << endl; 
    return x; 
} 
int main() { 
    HowMany2 h("h");//statement 1 
    out << "Entering f()" << endl; 
    HowMany2 h2 = f(h);//statement 2 
    h2.print("h2 after call to f()"); 
    out << "Call f(), no return value" << endl; 
    f(h);//statement 3 
    out << "After call to f()" << endl; 
} 

據埃克爾,輸出爲:

HowMany2() 
h: objectCount = 1 
Entering f() 
HowMany2(const HowMany2&) 
h copy: objectCount = 2 
x argument inside f() 
h copy: objectCount = 2 
Returning from f() 
HowMany2(const HowMany2&) 
h copy copy: objectCount = 3 
~HowMany2() 
h copy: objectCount = 2 
h2 after call to f() 
h copy copy: objectCount = 2 
Thinking in C++ www.BruceEckel.com 
Call f(), no return value 
HowMany2(const HowMany2&) 
h copy: objectCount = 3 
x argument inside f() 
h copy: objectCount = 3 
Returning from f() 
HowMany2(const HowMany2&) 
h copy copy: objectCount = 4 
~HowMany2() 
h copy: objectCount = 3 
~HowMany2() 
h copy copy: objectCount = 2 
After call to f() 
~HowMany2() 
h copy copy: objectCount = 1 
~HowMany2() 
h: objectCount = 0 

而且我們爲什麼不能爲返回值分配額外的存儲空間,讓我們可以將它們有一個函數調用之前存儲。它可以成爲使用引用的替代方法嗎? 提前謝謝!

回答

2

沒有拷貝構造函數的調用,因爲函數的返回值被忽略。
注意,即使可能需要一個副本大多數編譯器允許以避免在某些情況下通過複製省略拷貝構造函數調用。

由於x是對象本地的功能(有一個傳值),x被破壞一旦功能範圍{ }結束。

+0

但是,當我們看到輸出時,它顯示確實複製構造函數是爲返回值調用的,後來被破壞。這就是爲什麼我懷疑爲什麼編譯器不應該忽略這個調用。 – 2013-03-08 16:36:59

+0

@KavishDwivedi:你確定它是複製構造函數調用*返回值*?請注意,有一個複製構造函數調用需要*通過值*(您的函數參數是通過值)以及。你是否將前者誤解爲後者? – 2013-03-08 16:42:03

+0

:不,不是,我剛剛第二次閱讀了複製構造函數的這一章,但Eckel的輸出顯示對於複製構造函數,objectcount增加了。 – 2013-03-08 16:49:45

2

對於其他兩個語句(1和2)我可以推斷的是,編譯器防止bitcopying因爲我們已經指定了類中的拷貝構造函數,而是處理它通過我們的對象定義的拷貝構造函數傳遞給函數內部以及函數返回的對象。在函數結束之前,函數內的臨時對象被複製爲返回值,然後被破壞。我對嗎?

在C++:

  1. 臨時是移動構造的從返回的對象(如果沒有定義的移入構造,這將是一個複製結構);然後,
  2. 到的返回值被分配的對象是 移動分配(如果使用的t = f())或移動構造的(如果 使用T t = f())從返回的值(移動賦值變爲複製分配如果沒有定義移動賦值操作符,如果沒有定義移動構造函數,則移動構造變爲複製構造);然後,
  3. 臨時被破壞。

有一個很難理解的語句3時,有沒有回報,即使該函數的聲明和定義需要的對象副本的目的要返回

如果你不使用返回的值,編譯器沒有真正的理由調用任何複製構造函數。從函數返回時,返回的對象將簡單地超出範圍,這就是一切。

如果你看到拷貝構造這裏打電話,這可能是由於編譯器沒有優化掉步驟2和3以上(編譯器允許,但需要不,以退出通話)。

相關問題