主頁 > 後端開發 > <一>函式模板

<一>函式模板

2022-11-16 06:15:59 後端開發

函式模板
模板的意義:對型別也引數化
int sum1(int a,int b){return a+b;}
double sum2(double a ,double b){return a+b;}

幾個概念
函式模板
模板的實體化
模板函式

模板型別引數
模板非型別引數

模板實參推演
模板的特例化
模板函式,模板的特例化,非模板函式的多載關系

點擊查看代碼
template<typename T,typename E> //定義一個模板引數串列 或者用 class T 也可以

bool compare(T x ){ //compare 是一個函式模板,它目前只是個模板
   cout<<"Template Compare"<<endl;
   return x>y;
}

int main(){
    //函式的呼叫點,在函式呼叫點,編譯器用用戶指定的型別,從原模板實體化一份函式代碼出來
    // bool compare<int>(int a,int b){return a>b;}  這個從模板實體化出來的函式 就叫模板函式
    // bool compare<double>(double a, double b){return a>b} 這個從模板實體化出來的函式 就叫模板函式
    //模板函式是編譯器根據指定的型別從模板實體化出來 參與編譯的函式
    //從用戶的角度來看,我們只寫了一份模板代碼,代碼量是變少了,但是對于編譯器來說,需要編譯的代碼沒有減少,都需要根據指定的型別實體化出來具體函式
   
    compare<int>(1,2);//

    compare(100,200);//也可以,編譯器會根據實參型別進行推演出 compare<int> 進行模板的實體化.

    //注意如果有compare<int>(1,2); 然后有compare(100,200);
    //編譯器不會生成兩套同樣的 bool compare<int>(int a,int b){return a>b;},因為這個函式是需要在編譯期間生成符號表,
    //如果生成兩次,會出現在符號表中重名問題


    return 1;
}

示例代碼2 不實體話模板 并查看編譯后.o檔案中的 符號表情況

點擊查看代碼
#include <iostream>
using namespace std;

template<typename T>
bool compare(T x,T y){
    return x,y;
}

int main(){
    return 1;
}

//編譯后查看.o檔案中的符號表資訊如下 符號表中看不到compare函式的符號

kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
0000000000001258 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002008 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002060 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002004 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
0000000000001178 l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
00000000000011c5 l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000021a4 l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002008 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  000000000000000f              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
0000000000001258 g     F .fini  0000000000000000              .hidden _fini
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
00000000000011e0 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000001250 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4


示例代碼3 實體化模板 并查看編譯后.o檔案中的 符號表情況

點擊查看代碼
#include <iostream>
using namespace std;

template<typename T>
bool compare(T x,T y){
    return x,y;
}

int main(){
    bool b=compare<int>(100,200);
    return 1;
}

//編譯生成.o檔案,查看其中的符號表資訊, 在其中找到了 compare函式的符號表

kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
0000000000001288 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002008 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002068 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002004 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
000000000000118e l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
00000000000011db l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000021cc l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002008 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
00000000000011f4  w    F .text  0000000000000017              _Z7compareIiEbT_S0_        //compare函式的符號
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  0000000000000025              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
0000000000001288 g     F .fini  0000000000000000              .hidden _fini
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000001210 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000001280 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4


示例代碼4 實體化2次模板一次指定型別,一次引數型別自動推演 兩個型別是一樣的情況下 并查看編譯后.o檔案中的 符號表情況

點擊查看代碼
#include <iostream>
using namespace std;

template<typename T>
bool compare(T x,T y){
    return x,y;
}

int main(){
    bool b =compare<int>(100,200);
    bool b2=compare(400,200);
    return 1;
}

//編譯生成.o檔案,查看其中的符號表資訊, 在其中找到了一處compare函式的符號表

kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
0000000000001298 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002008 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002068 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002004 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
00000000000011a0 l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
00000000000011ed l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000021cc l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002008 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
0000000000001206  w    F .text  0000000000000017              _Z7compareIiEbT_S0_    //此處為compare的函式符號
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  0000000000000037              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
0000000000001298 g     F .fini  0000000000000000              .hidden _fini
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000001220 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000001290 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4


示例代碼5 實體化2次模板 兩次模板的引數型別不一樣 并查看編譯后.o檔案中的 符號表情況

點擊查看代碼
#include <iostream>
using namespace std;

template<typename T>
bool compare(T x,T y){
    return x,y;
}

int main(){
    bool b =compare<int>(100,200);
    bool b2=compare(400,200);
    bool b3=compare<double>(1.0,2.0);
    return 1;
}

//編譯生成.o檔案,查看其中的符號表資訊, 在其中找到了兩處處compare函式的符號表,一次是int 一次是double

kl@kl-ThinkPad-T580:/data/usershare/code/compile$ g++ TemplateTest1.cpp -o test1.o
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
00000000000012e8 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002020 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002088 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002008 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
00000000000011c0 l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
000000000000120d l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
000000000000220c l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002020 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
0000000000001226  w    F .text  0000000000000017              _Z7compareIiEbT_S0_         //compare<int>(int a,int b) 函式符號
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  0000000000000057              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
00000000000012e8 g     F .fini  0000000000000000              .hidden _fini
000000000000123d  w    F .text  0000000000000031              _Z7compareIdEbT_S0_           //compare<double>(double a ,double b) 函式符號
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000001270 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
00000000000012e0 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4



//我們順便看一下.o 檔案生成的指令   

kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -S test1.o

test1.o:     檔案格式 elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:       f3 0f 1e fa             endbr64 
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   callq  *%rax
    1016:       48 83 c4 08             add    $0x8,%rsp
    101a:       c3                      retq   

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:       ff 35 8a 2f 00 00       pushq  0x2f8a(%rip)        # 3fb0 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:       f2 ff 25 8b 2f 00 00    bnd jmpq *0x2f8b(%rip)        # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:       0f 1f 00                nopl   (%rax)
    1030:       f3 0f 1e fa             endbr64 
    1034:       68 00 00 00 00          pushq  $0x0
    1039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt>
    103f:       90                      nop
    1040:       f3 0f 1e fa             endbr64 
    1044:       68 01 00 00 00          pushq  $0x1
    1049:       f2 e9 d1 ff ff ff       bnd jmpq 1020 <.plt>
    104f:       90                      nop

Disassembly of section .plt.got:

0000000000001050 <__cxa_finalize@plt>:
    1050:       f3 0f 1e fa             endbr64 
    1054:       f2 ff 25 75 2f 00 00    bnd jmpq *0x2f75(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
    105b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001060 <__cxa_atexit@plt>:
    1060:       f3 0f 1e fa             endbr64 
    1064:       f2 ff 25 55 2f 00 00    bnd jmpq *0x2f55(%rip)        # 3fc0 <__cxa_atexit@GLIBC_2.2.5>
    106b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

0000000000001070 <_ZNSt8ios_base4InitC1Ev@plt>:
    1070:       f3 0f 1e fa             endbr64 
    1074:       f2 ff 25 4d 2f 00 00    bnd jmpq *0x2f4d(%rip)        # 3fc8 <_ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4>
    107b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .text:

0000000000001080 <_start>:
    1080:       f3 0f 1e fa             endbr64 
    1084:       31 ed                   xor    %ebp,%ebp
    1086:       49 89 d1                mov    %rdx,%r9
    1089:       5e                      pop    %rsi
    108a:       48 89 e2                mov    %rsp,%rdx
    108d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1091:       50                      push   %rax
    1092:       54                      push   %rsp
    1093:       4c 8d 05 46 02 00 00    lea    0x246(%rip),%r8        # 12e0 <__libc_csu_fini>
    109a:       48 8d 0d cf 01 00 00    lea    0x1cf(%rip),%rcx        # 1270 <__libc_csu_init>
    10a1:       48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 1169 <main>
    10a8:       ff 15 32 2f 00 00       callq  *0x2f32(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>
    10ae:       f4                      hlt    
    10af:       90                      nop

00000000000010b0 <deregister_tm_clones>:
    10b0:       48 8d 3d 59 2f 00 00    lea    0x2f59(%rip),%rdi        # 4010 <__TMC_END__>
    10b7:       48 8d 05 52 2f 00 00    lea    0x2f52(%rip),%rax        # 4010 <__TMC_END__>
    10be:       48 39 f8                cmp    %rdi,%rax
    10c1:       74 15                   je     10d8 <deregister_tm_clones+0x28>
    10c3:       48 8b 05 0e 2f 00 00    mov    0x2f0e(%rip),%rax        # 3fd8 <_ITM_deregisterTMCloneTable>
    10ca:       48 85 c0                test   %rax,%rax
    10cd:       74 09                   je     10d8 <deregister_tm_clones+0x28>
    10cf:       ff e0                   jmpq   *%rax
    10d1:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    10d8:       c3                      retq   
    10d9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

00000000000010e0 <register_tm_clones>:
    10e0:       48 8d 3d 29 2f 00 00    lea    0x2f29(%rip),%rdi        # 4010 <__TMC_END__>
    10e7:       48 8d 35 22 2f 00 00    lea    0x2f22(%rip),%rsi        # 4010 <__TMC_END__>
    10ee:       48 29 fe                sub    %rdi,%rsi
    10f1:       48 89 f0                mov    %rsi,%rax
    10f4:       48 c1 ee 3f             shr    $0x3f,%rsi
    10f8:       48 c1 f8 03             sar    $0x3,%rax
    10fc:       48 01 c6                add    %rax,%rsi
    10ff:       48 d1 fe                sar    %rsi
    1102:       74 14                   je     1118 <register_tm_clones+0x38>
    1104:       48 8b 05 e5 2e 00 00    mov    0x2ee5(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable>
    110b:       48 85 c0                test   %rax,%rax
    110e:       74 08                   je     1118 <register_tm_clones+0x38>
    1110:       ff e0                   jmpq   *%rax
    1112:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    1118:       c3                      retq   
    1119:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001120 <__do_global_dtors_aux>:
    1120:       f3 0f 1e fa             endbr64 
    1124:       80 3d e5 2e 00 00 00    cmpb   $0x0,0x2ee5(%rip)        # 4010 <__TMC_END__>
    112b:       75 2b                   jne    1158 <__do_global_dtors_aux+0x38>
    112d:       55                      push   %rbp
    112e:       48 83 3d 9a 2e 00 00    cmpq   $0x0,0x2e9a(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
    1135:       00 
    1136:       48 89 e5                mov    %rsp,%rbp
    1139:       74 0c                   je     1147 <__do_global_dtors_aux+0x27>
    113b:       48 8b 3d c6 2e 00 00    mov    0x2ec6(%rip),%rdi        # 4008 <__dso_handle>
    1142:       e8 09 ff ff ff          callq  1050 <__cxa_finalize@plt>
    1147:       e8 64 ff ff ff          callq  10b0 <deregister_tm_clones>
    114c:       c6 05 bd 2e 00 00 01    movb   $0x1,0x2ebd(%rip)        # 4010 <__TMC_END__>
    1153:       5d                      pop    %rbp
    1154:       c3                      retq   
    1155:       0f 1f 00                nopl   (%rax)
    1158:       c3                      retq   
    1159:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001160 <frame_dummy>:
    1160:       f3 0f 1e fa             endbr64 
    1164:       e9 77 ff ff ff          jmpq   10e0 <register_tm_clones>

0000000000001169 <main>:
    1169:       f3 0f 1e fa             endbr64 
    116d:       55                      push   %rbp
    116e:       48 89 e5                mov    %rsp,%rbp
    1171:       48 83 ec 10             sub    $0x10,%rsp
    1175:       be c8 00 00 00          mov    $0xc8,%esi
    117a:       bf 64 00 00 00          mov    $0x64,%edi
    117f:       e8 a2 00 00 00          callq  1226 <_Z7compareIiEbT_S0_>   //compare<int>(100,200);
    1184:       88 45 fd                mov    %al,-0x3(%rbp)
    1187:       be c8 00 00 00          mov    $0xc8,%esi
    118c:       bf 90 01 00 00          mov    $0x190,%edi
    1191:       e8 90 00 00 00          callq  1226 <_Z7compareIiEbT_S0_>   //compare(400,200); 和上面呼叫的函式是一個函式
    1196:       88 45 fe                mov    %al,-0x2(%rbp)
    1199:       f2 0f 10 05 6f 0e 00    movsd  0xe6f(%rip),%xmm0        # 2010 <_ZStL19piecewise_construct+0x8>
    11a0:       00 
    11a1:       48 8b 05 70 0e 00 00    mov    0xe70(%rip),%rax        # 2018 <_ZStL19piecewise_construct+0x10>
    11a8:       66 0f 28 c8             movapd %xmm0,%xmm1
    11ac:       66 48 0f 6e c0          movq   %rax,%xmm0
    11b1:       e8 87 00 00 00          callq  123d <_Z7compareIdEbT_S0_>  //   bool b3=compare<double>(1.0,2.0);  double 型別的函式
    11b6:       88 45 ff                mov    %al,-0x1(%rbp)
    11b9:       b8 01 00 00 00          mov    $0x1,%eax
    11be:       c9                      leaveq 
    11bf:       c3                      retq   

00000000000011c0 <_Z41__static_initialization_and_destruction_0ii>:
    11c0:       f3 0f 1e fa             endbr64 
    11c4:       55                      push   %rbp
    11c5:       48 89 e5                mov    %rsp,%rbp
    11c8:       48 83 ec 10             sub    $0x10,%rsp
    11cc:       89 7d fc                mov    %edi,-0x4(%rbp)
    11cf:       89 75 f8                mov    %esi,-0x8(%rbp)
    11d2:       83 7d fc 01             cmpl   $0x1,-0x4(%rbp)
    11d6:       75 32                   jne    120a <_Z41__static_initialization_and_destruction_0ii+0x4a>
    11d8:       81 7d f8 ff ff 00 00    cmpl   $0xffff,-0x8(%rbp)
    11df:       75 29                   jne    120a <_Z41__static_initialization_and_destruction_0ii+0x4a>
    11e1:       48 8d 3d 29 2e 00 00    lea    0x2e29(%rip),%rdi        # 4011 <_ZStL8__ioinit>
    11e8:       e8 83 fe ff ff          callq  1070 <_ZNSt8ios_base4InitC1Ev@plt>
    11ed:       48 8d 15 14 2e 00 00    lea    0x2e14(%rip),%rdx        # 4008 <__dso_handle>
    11f4:       48 8d 35 16 2e 00 00    lea    0x2e16(%rip),%rsi        # 4011 <_ZStL8__ioinit>
    11fb:       48 8b 05 f6 2d 00 00    mov    0x2df6(%rip),%rax        # 3ff8 <_ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4>
    1202:       48 89 c7                mov    %rax,%rdi
    1205:       e8 56 fe ff ff          callq  1060 <__cxa_atexit@plt>
    120a:       90                      nop
    120b:       c9                      leaveq 
    120c:       c3                      retq   

000000000000120d <_GLOBAL__sub_I_main>:
    120d:       f3 0f 1e fa             endbr64 
    1211:       55                      push   %rbp
    1212:       48 89 e5                mov    %rsp,%rbp
    1215:       be ff ff 00 00          mov    $0xffff,%esi
    121a:       bf 01 00 00 00          mov    $0x1,%edi
    121f:       e8 9c ff ff ff          callq  11c0 <_Z41__static_initialization_and_destruction_0ii>
    1224:       5d                      pop    %rbp
    1225:       c3                      retq   

0000000000001226 <_Z7compareIiEbT_S0_>:  // compare<int>(int a, int b)
    1226:       f3 0f 1e fa             endbr64 
    122a:       55                      push   %rbp
    122b:       48 89 e5                mov    %rsp,%rbp
    122e:       89 7d fc                mov    %edi,-0x4(%rbp)
    1231:       89 75 f8                mov    %esi,-0x8(%rbp)
    1234:       83 7d f8 00             cmpl   $0x0,-0x8(%rbp)
    1238:       0f 95 c0                setne  %al
    123b:       5d                      pop    %rbp
    123c:       c3                      retq   

000000000000123d <_Z7compareIdEbT_S0_>:     //compare<double>(1.0,2.0); double 型別的函式
    123d:       f3 0f 1e fa             endbr64 
    1241:       55                      push   %rbp
    1242:       48 89 e5                mov    %rsp,%rbp
    1245:       f2 0f 11 45 f8          movsd  %xmm0,-0x8(%rbp)
    124a:       f2 0f 11 4d f0          movsd  %xmm1,-0x10(%rbp)
    124f:       66 0f ef c0             pxor   %xmm0,%xmm0
    1253:       66 0f 2e 45 f0          ucomisd -0x10(%rbp),%xmm0
    1258:       0f 9a c0                setp   %al
    125b:       ba 01 00 00 00          mov    $0x1,%edx
    1260:       66 0f ef c0             pxor   %xmm0,%xmm0
    1264:       66 0f 2e 45 f0          ucomisd -0x10(%rbp),%xmm0
    1269:       0f 45 c2                cmovne %edx,%eax
    126c:       5d                      pop    %rbp
    126d:       c3                      retq   
    126e:       66 90                   xchg   %ax,%ax

0000000000001270 <__libc_csu_init>:
    1270:       f3 0f 1e fa             endbr64 
    1274:       41 57                   push   %r15
    1276:       4c 8d 3d 13 2b 00 00    lea    0x2b13(%rip),%r15        # 3d90 <__frame_dummy_init_array_entry>
    127d:       41 56                   push   %r14
    127f:       49 89 d6                mov    %rdx,%r14
    1282:       41 55                   push   %r13
    1284:       49 89 f5                mov    %rsi,%r13
    1287:       41 54                   push   %r12
    1289:       41 89 fc                mov    %edi,%r12d
    128c:       55                      push   %rbp
    128d:       48 8d 2d 0c 2b 00 00    lea    0x2b0c(%rip),%rbp        # 3da0 <__do_global_dtors_aux_fini_array_entry>
    1294:       53                      push   %rbx
    1295:       4c 29 fd                sub    %r15,%rbp
    1298:       48 83 ec 08             sub    $0x8,%rsp
    129c:       e8 5f fd ff ff          callq  1000 <_init>
    12a1:       48 c1 fd 03             sar    $0x3,%rbp
    12a5:       74 1f                   je     12c6 <__libc_csu_init+0x56>
    12a7:       31 db                   xor    %ebx,%ebx
    12a9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    12b0:       4c 89 f2                mov    %r14,%rdx
    12b3:       4c 89 ee                mov    %r13,%rsi
    12b6:       44 89 e7                mov    %r12d,%edi
    12b9:       41 ff 14 df             callq  *(%r15,%rbx,8)
    12bd:       48 83 c3 01             add    $0x1,%rbx
    12c1:       48 39 dd                cmp    %rbx,%rbp
    12c4:       75 ea                   jne    12b0 <__libc_csu_init+0x40>
    12c6:       48 83 c4 08             add    $0x8,%rsp
    12ca:       5b                      pop    %rbx
    12cb:       5d                      pop    %rbp
    12cc:       41 5c                   pop    %r12
    12ce:       41 5d                   pop    %r13
    12d0:       41 5e                   pop    %r14
    12d2:       41 5f                   pop    %r15
    12d4:       c3                      retq   
    12d5:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
    12dc:       00 00 00 00 

00000000000012e0 <__libc_csu_fini>:
    12e0:       f3 0f 1e fa             endbr64 
    12e4:       c3                      retq   

Disassembly of section .fini:

00000000000012e8 <_fini>:
    12e8:       f3 0f 1e fa             endbr64 
    12ec:       48 83 ec 08             sub    $0x8,%rsp
    12f0:       48 83 c4 08             add    $0x8,%rsp
    12f4:       c3                      retq   




如果compare(100,1.1) // 編譯器推演失敗 可以 comare(100,1.1);讓編譯器強轉

函式模板是無法編譯的,也不進行編譯的,函式模板在呼叫點發生模板實體化動作,被實體化化后 成為模板函式,模板函式才是真正參與編譯的

關于模板特例化
如果有compare("aaa",bbb“”); 此時模板會自動推到出如下
compare<const char *>(const char * x,const char * y){
return x>y;
}

上面的比較方式會去比較兩個指標地址大小,這種方式不是我們想要的邏輯,所以我們需要根據const char * 寫一個特殊的實作方法邏輯如下
template<>
bool compare<const char *>(const char *x ,const char * y){
return strcmp(x,y);
}
那么上面這個函式就叫做模板的特例化 特例化特殊在不再由編譯器自動生成函式,使用自己的實作方式


普通函式和函式模板選擇問題 示例代碼

點擊查看代碼
如果有
//這是個函式模板
template<>
bool compare<const char *>(const char *x ,const char * y){
     return strcmp(x,y);
}
//這是一個普通的函式
bool compare(const char *x ,const char * y){
     return strcmp(x,y);
}

有
bool b=compare("aa","bb");//那么編譯器會優選能匹配的普通的函式,避免編譯器再去生成函式

bool b1=compare<const char *>("aa","bb");//這個時候會使用模板特例化


//所以我們會遇到 函式模板, 模板特例化, 普通函式都可以匹配呼叫的時候,如何選擇需要知道,自動推演有普通函式能用的,用普通函式,沒有普通函式如果有模板特例化的用特例化,沒有特例化的,編譯器去生成指定型別函式

下面我們看一下模板和呼叫點分檔案撰寫遇到的問題

只有函式模板,編譯后查看符號表情況,點擊查看代碼
// test1.cpp 代碼如下
#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}

//test1.cpp 編譯后 符號表情況如下,編譯后沒有 函式符號
uos20@uos20-PC:~/Desktop/CPP$ g++ -c test1.cpp -o test1.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test1.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
0000000000000000 l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
000000000000003e l     F .text  0000000000000015 _GLOBAL__sub_I_test1.cpp
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit


有函式模板及一個特例化,編譯后查看符號表情況,點擊查看代碼
// test1.cpp 代碼如下

#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//模板特例化
template<>
bool compare(const char * x, const char * y){
   return strcmp(x,y);
}

//test1.cpp 編譯后 符號表情況如下,編譯后沒有 函式符號

uos20@uos20-PC:~/Desktop/CPP$ g++ -c test1.cpp -o test1.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test1.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
000000000000002a l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
0000000000000068 l     F .text  0000000000000015 _GLOBAL__sub_I__Z7compareIPKcEbT_S2_    // 特例化函式符號compare
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     F .text  000000000000002a _Z7compareIPKcEbT_S2_
0000000000000000         *UND*  0000000000000000 strcmp
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit


有函式模板及一個特例化和一個普通函式,編譯后查看符號表情況,點擊查看代碼
// test1.cpp 代碼如下

#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//模板特例化
template<>
bool compare(const char * x, const char * y){
   return strcmp(x,y);
}

//這是一個普通的函式,不是模板,與模板無關
bool  compare( const char  * x,  const char  * y){
    return x>y;
}

//編譯完成后,我們再符號表中 看到兩處 compare ,一處是特例化,一處是 普通compare函式
uos20@uos20-PC:~/Desktop/CPP$ g++ -c test1.cpp -o test1.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test1.o

test1.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test1.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
0000000000000043 l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
0000000000000081 l     F .text  0000000000000015 _GLOBAL__sub_I__Z7compareIPKcEbT_S2_
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     F .text  000000000000002a _Z7compareIPKcEbT_S2_  //compare 函式符號
0000000000000000         *UND*  0000000000000000 strcmp
000000000000002a g     F .text  0000000000000019 _Z7comparePKcS0_    //compare函式符號
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit
分檔案撰寫,測驗代碼1,點擊查看代碼
// test1.cpp
#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}

//test2.cpp
#include <iostream>
#include <cstring>
using namespace std;

template<typename T>
bool compare(T x, T y);

int main() {
   bool b1 = compare<int>(1, 2);
   bool b2 = compare<double>(100.1, 200.1);
   return 1;

}

// 編譯 報 兩處錯  
//無法決議的外部符號 "bool __cdecl compare<double>(double,double)
//無法決議的外部符號 "bool __cdecl compare<int>(int,int)

//為什么會出現鏈接錯誤?我先看一下test2.cpp編譯后的符號表情況 如下

uos20@uos20-PC:~/Desktop/CPP$ g++ -c test2.cpp -o test2.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test2.o

test2.o:     檔案格式 elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test2.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
0000000000000039 l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
0000000000000077 l     F .text  0000000000000015 _GLOBAL__sub_I_main
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     F .text  0000000000000039 main
0000000000000000         *UND*  0000000000000000 _Z7compareIiEbT_S0_   //compare<int> 函式符號    UND形式
0000000000000000         *UND*  0000000000000000 _Z7compareIdEbT_S0_   //compare<double> 函式符號 UND形式
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit


//test2.cpp 和 test1.cpp 分離編譯,test2.cpp 有 compare<int>函式符號 UND(外部參考) 和 compare<double>函式符號 UND(外部參考)
//然而test1.cpp只是模板 編譯時 沒有 compare<int>(int a,int b) 和compare<double>(double a, double b)產生編譯,
//所以鏈接的時候,test2.o 的 UND函式需要去其他目標檔案中找compare<int>(int a, int b)和compare<double>(double a, double b)的定義,找不到,編譯報錯



分檔案撰寫,測驗代碼2,點擊查看代碼
// test1.cpp
#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//模板特例化
template<>
bool compare<const char *>(const char * x, const char * y) {
	return strcmp(x, y);
}

//test2.cpp
#include <iostream>
#include <cstring>
using namespace std;

template<typename T>
bool compare(T x, T y);

int main() {
   bool b3 = compare("aaa", "bbb");
   return 1;

}

//正常編譯通過并呼叫

分檔案撰寫,測驗代碼3 ,點擊查看代碼
//test1.cpp
#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x, T y) {
	return x, y;
}

 
//模板特例化
template<>
bool compare<const char *>(const char * x, const char * y) {
	cout << "Template Function" << endl;
	return strcmp(x, y);
}


//這是一個普通的函式,不是模板,與模板無關
bool  compare(const char  * x, const char  * y) {
	cout << "Normal Function" << endl;
	return x>y;
}


//test2.cpp

#include <iostream>
#include <cstring>
using namespace std;

template<typename T>
bool compare(T x, T y);

bool  compare(const char  * x, const char  * y);

int main() {
  bool b3 = compare("aaa", "bbb");
  return 1;
}

//正常編譯通過,呼叫普通函式

分檔案撰寫,測驗代碼4,點擊查看代碼
// test1.cpp

#include <iostream>
#include <cstring>
using namespace std;

//這是一個函式模板
template<typename T>
bool compare(T x, T y) {
	return x, y;
}

//模板特例化
template<>
bool compare<const char *>(const char * x, const char * y) {
	cout << "Template Function" << endl;
	return strcmp(x, y);
}

//這是一個普通的函式,不是模板,與模板無關
bool  compare(const char  * x, const char  * y) {
	cout << "Normal Function" << endl;
	return x>y;
}
//編譯后, .o檔案中有兩處 compare函式符號,一處是 普通函式的,一處是 模板特例化函式的


// test2.cpp 情況1  下面test2.cpp編譯后,.o檔案中沒有compare函式符號

#include <iostream>
#include <cstring>
using namespace std;

//模板宣告
template<typename T>
bool compare(T x, T y);

int main() {
    system("pause");
    return 1;

}

// test2.cpp 情況2  下面test2.cpp編譯后,.o檔案中仍然沒有compare函式符號
#include <iostream>
#include <cstring>
using namespace std;

//模板宣告
template<typename T>
bool compare(T x, T y);
//普通函式宣告
bool  compare(const char  * x, const char  * y);

int main() {
    system("pause");
    return 1;

}

// test2.cpp 情況3  下面test2.cpp編譯后,.o檔案中有compare函式符號,編譯報鏈接錯誤,因為找不到compare<int>(int a,int b),test1.cpp中只是模板
#include <iostream>
#include <cstring>
using namespace std;

//模板宣告
template<typename T>
bool compare(T x, T y);

int main() {
    bool b1 = compare<int>(1, 2);
    system("pause");
    return 1;

}

// test2.cpp 情況4  下面test2.cpp編譯后,.o檔案中有compare函式符號,編譯通過
// bool b1 = compare("AA", "BB");這個呼叫點會根據模板宣告,生成函式符號,
// 而在test1.cpp 中有個模板特例化的實作,所以鏈接能找到

#include <iostream>
#include <cstring>
using namespace std;

//模板宣告
template<typename T>
bool compare(T x, T y);

int main() {
    bool b1 = compare("AA", "BB");
    system("pause");
    return 1;

}


//  test2.cpp 情況5  bool b1 = compare("AA", "BB");如果想調普通函式 那么代碼如下,加上普通函式宣告
//  bool b1 = compare("AA", "BB");呼叫點發現有普通函式宣告 bool  compare(const char  * x, const char  * y);能匹配
//  那么就按照這個生成函式符號, 而在 test1.cpp中有普通函式的具體實作,所以編譯通過,呼叫普通函式
#include <iostream>
#include <cstring>
using namespace std;

//模板宣告
template<typename T>
bool compare(T x, T y);

//普通函式宣告
bool  compare(const char  * x, const char  * y);

int main() {
    bool b1 = compare("AA", "BB");
    system("pause");
    return 1;

}


// test2.cpp 情況6  呼叫點bool b1 = compare("AA", "BB");如果有普通函式宣告 bool  compare(const char  * x, const char  * y);
//還是想呼叫 模板特例化函式,那么要呼叫點要這么寫 bool b1 = compare<const char *>("AA", "BB"); 如下
//在函式呼叫點 bool b1 = compare<const char *>("AA", "BB"); 會根據宣告的模板去生成函式符號,同時在test1.cpp中又有模板特例化函式
//所以能找到匹配的,順利呼叫
#include <iostream>
#include <cstring>
using namespace std;

//模板宣告
template<typename T>
bool compare(T x, T y);

//普通函式宣告
bool  compare(const char  * x, const char  * y);

int main() {
    bool b1 = compare<const char *>("AA", "BB");
    system("pause");
    return 1;

}


前面提到的模板和呼叫點分檔案撰寫,有鏈接問題,如何解決?

1:模板宣告的檔案加上以下陳述句,強制編譯器按照指定型別實體化,生成指定的函式,是的其他檔案中的呼叫點 在鏈接的時候能找到函式
template bool compare(int,int);
template bool compare(double ,double);

2:加模板宣告寫在頭檔案中,在呼叫點檔案include 進來

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/534052.html

標籤:C++

上一篇:Visual Studio C++ 默認 UTF-8 編碼及 *.editorconfig 統一代碼格式

下一篇:計算機等級考試二級C語言程式設計專項訓練題——程式填空題(一)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more