cc c 發問時間: 電腦與網際網路程式設計 · 1 0 年前

C++:template進行instantiation的時機

大家好,我在看C++template,

書中介紹到template進行instantiation的時機,

它說:

---

class template進行instantiation的時機是「定義class object」時。

定義class pointer不會進行instantiation,只有使用該pointer會進行instantiation。

member-function template進行instantiation的時機,

是在呼叫member function時。如果沒有呼叫該member function。

則不會進行該member function的instantiation。

---

書中內容只有這樣,但它有個習題讓我小小疑惑,

因為沒有解答,所以想請C++達人印證一下我的觀念是否有錯。

如下例,各個位置是否有進行instantiation呢?

---

template <class T> class Stack { };

void f1(Stack<char>); //(a)沒有 (當f1實際傳入argument時,才生成Stack<char>instance)

class Exercise {

Stack<double> &rsd; //(b)沒有 (和pointer一樣道理,使用rsd才生成Stack<double>實例)

Stack<int> si; //(c)有

};

int main() {

Stack<char> *sc; //(d)沒有

f1(*sc); //(e)有

int iObj = sizeof(Stack< string >); //(f)沒有

}

---

謝謝

已更新項目:

說明一下:instantiation指「template實例化」

2 個已更新項目:

我對sizeof有點疑問,

只是要計算data member容量而已,compiler也要把實體做出來才計算嗎?

3 個已更新項目:

在您的參考網頁中有說到:

The compiler does not instantiate the class template until a reference to a member of this template class is made, sizeof is used on the class, or an instance is created.

這個說法和書中所提的好像有點出入,例如:

4 個已更新項目:

「Stack obj;」

生成object,但還沒有使用member。

依C++ primer所述,生成object即會生成class instance,但還不會生成function instance。

我是否乎略了什麼呢?

5 個已更新項目:

sorry,是「Stack<int> obj;」

6 個已更新項目:

sorry,我忽略最基本的constructor了。>

7 個已更新項目:

這麼說來,下列二個情況有點疑問,

1.「void f1(Stack a){}」若不呼叫f1,會產生instance嗎?

2.「class Exercise{Stack si;};」只是一個member,

並沒有初始化,為什麼它也會產生instance?

8 個已更新項目:

sorry,知識家每次都吃字,我每次都忘記…,下次這二個才是我的疑問

「void f1(Stack<int> a){}」

「class Exercise{Stack<int> si;};」

9 個已更新項目:

sorry,知識家每次都吃字,我每次都忘記…,下面這二個才是我的疑問

「void f1(Stack<int> a){}」

「class Exercise{Stack<int> si;};」

10 個已更新項目:

這麼說來,不一定要初始化「Stack <int>」才會生成instance,

例如說:

1.「void f1 (Stack<int>);」

沒有function definition,就沒有instance

2.「void f1 (Stack<int>){}」

有function definition,不一定要呼叫也會生成instance (看compiler)

11 個已更新項目:

3.「Stack<int> obj;」和「class C {Stack<int> obj};」

都會產生instance,是不是class member沒有關係,也不一定要定義class C object。

4.「sizeof(Stack<int>)」

要reference到member才能計算size,所以也有instantiation

12 個已更新項目:

^ ^ 這四個理清應該就ok了,非常感謝您

1 個解答

評分
  • Lv 7
    1 0 年前
    最佳解答

    俺的想法是這樣的.

    void f1(Stack<char>);

    不懂"當f1實際傳入argument時,才生成"是啥意思.這並無.因這只是個function prototype.

    void f1(Stack<char> a)

    {

    }...

    這就有了.因compiler要找出Stack<char>有多大,才能正確的產生assembly code. 比如說你的stack<>是

    template <class t> class Stack {

    public:

    t data;

    };

    你若是用void f1(Stack<char> a)那compiler只需要用1bytes(或一個register)來傳引數.但你若是用void f1(Stack<string> a)的話那compiler就需要不只一個byte了.

    Stack<double> &rsd;

    沒有.

    Stack<int> si;

    有.

    Stack<char> *sc;

    沒有.

    int iObj = sizeof(Stack< string >);

    有.因compiler要找出Stack<char>有多大.用上面第一題的例子.Stack<char>和Stack<string>的大小是不一樣的.sizeof()是在compile時被處理掉的.

    懂不懂?不懂請再問

    2008-04-26 06:09:23 補充:

    void f1(Stack a) {}

    這要看編譯器了.你若不呼叫,有的編譯器在編譯時就不會編譯這函式.但有的會.

    不管會不會.如果編譯器編譯這函式.就會實例化.因你是用pass by value的方法.所以編譯器在編譯的時候要知道Stack 的大小.才能以pass by value的方法傳進.

    class Exercise{

    Stack si;

    };

    因Exercise並無template.所以在編譯會被編譯器reference到,所以會.

    2008-04-26 21:35:40 補充:

    void f1(Stack〈int〉 a) {}

    這要看編譯器了.你若不呼叫,有的編譯器在編譯時就不會編譯這函式.但有的會.

    不管會不會.如果編譯器編譯這函式.就會實例化.因你是用pass by value的方法.所以編譯器在編譯的時候要知道Stack 的大小.才能以pass by value的方法傳進.因此答案是有

    class Exercise{

    Stack〈int〉 si;

    };

    因你在Exercise裡有reference到Stack〈int〉,所以會.

    2008-04-27 01:28:41 補充:

    1. void f1 (Stack<int>);這只不過是個function prototype.這只不過告訴C++你有個function叫f1().所以並無reference.

    2. void f1 (Stack<int> a){}, 這是function definition.這告訴C++你有個f1()且f1()是用pass by value來傳Stack<int>這個引數.所以有.

    3. 對.

    4. 對.

    2008-04-27 01:28:46 補充:

    在判斷一個template是否會instantiate時.有一個簡單的方法.就是問一問自己,這句程式碼是否須要知道class的大小?

    比如說

    void f1 (Stack <int> &a) {};

    這會不會instantiate?因是以pass by reference所以並不需要知道Stack<int>的大小.所以不會.

    懂不懂?不懂請再問

    參考資料: Myself, http://msdn2.microsoft.com/en-us/library/7y5ca42y(... 懂不懂?不懂請再問, Myself, Myself, Myself
還有問題?馬上發問,尋求解答。