2015-04-05 40 views
2

我正在研究C++模板實例的詳細信息gcc 4.8.1和Linux上的選項-frepo。據我瞭解,這個選項會對模板實例進行一些清理,因此每個實例化只在鏈接二進制文件中出現一次,即使它在幾個翻譯單元中被隱式實例化。對於具體的語境,請參閱這些示例文件:C++內部類; 「nm -C」輸出中沒有符號

// file: template.h 
template <typename T> 
class Box { 
public: 
    void func (const T & t) {}  // member function 

    template <T t> 
    T func_tmpl() { return t; }  // member function template 

    template <T t> 
    class inner {      // inner class template 
    public: 
     const static T value = t; 
    }; 
}; 

// file: main.cpp 
#include "template.h" 

int main (int argc, char * argv[]) { 
    Box<int> b; 
    b.func(3);      // member function invocation 
    int x = b.func_tmpl<7>();   // member function temple instantiation 
    Box<int>::inner<5> g;    // inner class template instantiation 
    int y = g.value; 
    return 0; 
} 

當我編譯(g++ -frepo -c main.cpp),然後檢查符號(nm -C main.o)我發現:

0000000000000000 T main 
       U Box<int>::func(int const&) 
       U int Box<int>::func_tmpl<7>() 

如您所料,funcfunc_tmpl被列爲未定義的符號。我不清楚的是爲什麼inner沒有列出;它是在類模板中定義的,本身是類模板,並在main.cpp中實例化。任何人都可以建議inner未被包含在main.o符號中的原因,是否定義?

+0

'nm'不顯示類,它顯示函數和全局變量。它會顯示「框 ::內<5> ::價值」,除了它是「未使用」在這裏。 – 2015-04-05 19:45:20

+0

@MarcGlisse感謝您的快速回復。你的評論的第一句似乎是合理的,並會解釋一些事情。不過,我很好奇第二句話:我會如何使它「使用」?我嘗試了幾種方法,沒有明顯的效用。另外,是否「Box :: Inner <5> :: value'實際上是一個全局變量?我會認爲它的範圍更窄,因爲必須使用'::'來標識它。再次感謝! – 2015-04-05 20:14:14

回答

0

編譯器發現Box<int>::inner<5>::value是一個常量,目標代碼生成將它取出並用文字5代替名稱。如果你觀察生成的彙編代碼,你可能會看到類似:

movl $3, -12(%rbp) 
    leaq -12(%rbp), %rdx 
    leaq -13(%rbp), %rax 
    movq %rdx, %rsi 
    movq %rax, %rdi 
    call _ZN3BoxIiE4funcERKi 
    leaq -13(%rbp), %rax 
    movq %rax, %rdi 
    call _ZN3BoxIiE9func_tmplILi7EEEiv 
    movl %eax, -4(%rbp) 
    movl $5, -8(%rbp) 

相當於調用Box::func,然後調用Box::func_tmpl分配給x,然後分配給y。請注意,對y的分配使用文字值5

要使符號出現在您的nm輸出中,請使用成員本身,而不是其值。例如,存儲其參考:

const int &y = g.value; 
+0

我很感謝您的詳細解答。我沒有考慮不斷的優化。感謝你,下次我會重點介紹。我試圖爲你的答案投票,但顯然我首先需要更高的聲望。 – 2015-04-07 23:32:46