<一>函數模板

来源:https://www.cnblogs.com/erichome/archive/2022/11/15/16889476.html
-Advertisement-
Play Games

函數模板 模板的意義:對類型也參數化 int sum1(int a,int b){return a+b;} double sum2(double a ,double b){return a+b;} 幾個概念 函數模板 模板的實例化 模板函數 模板類型參數 模板非類型參數 模板實參推演 模板的特例化 ...


函數模板
模板的意義:對類型也參數化
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 進來


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 項目中需要計算使用年限,按月份算。剛開始踩了坑,不足1年應該按1年算。記錄下~ 和當前時間比較,用DATEDIFF函數DateDiff(month,比較的時間,getdate())先算出月份,再除以12算年份 查看代碼 --月份差值 2.083333 select CONVERT(decimal,D ...
  • 這裡說的占位符,實際就是排版時需要展示的圖片,圖片基於占位符填充,那麼處理圖片時,怎麼解決占位符(圖片)的上下偏移在設置占位符屬性時,我通過以下方法來實現它: + (NSAttributedString *)wxImageAttributeCoreTextFromPaperQuestion:(WXT ...
  • 本文繼續組件庫開發環境的搭建,前面兩篇分別介紹了組件庫中組件項目的初始化、組件庫 CSS 架構,本文介紹通用工具庫的搭建。在組件開發過程中,可能會調用一些通用的工具函數,這些工具函數便可以提取到一個獨立的 npm 包中。 ...
  • electron vue3 項目搭建 一.vue項目搭建 安裝electron 需要搭建vue項目,這裡用的vue3項目。 1.安裝 下載 node 這裡用的16版本 https://nodejs.org/zh-cn/ 2.設置淘寶鏡像 npm config set registry https:/ ...
  • 有足夠的地圖數據,可以點擊到街道,示例我只出到市級 以umi為框架,版本是: "react": "^18.2.0", "umi": "^4.0.29", "echarts": "^5.4.0", "echarts-for-react": "^3.0.2", 示例圖: 示例中需要地圖的Geojson數 ...
  • 瀑布流算是比較常見的佈局了,一個般常見縱向瀑布流的交互,當我們滾動到底的時候載入下一頁的數據追加到上去。因為一次載入的數據量不是很多,頁面操作是也不會有太大的性能消耗。但是如果當你一直往下滾動載入,載入幾十頁的時候,就會開始感覺不那麼流暢的,這是因為雖然每次操作的很少,但是頁面的 DOM 越來越多,... ...
  • vue中的ajax vue腳手架配置代理 方法一 ​ 在vue.config.js中添加如下配置: devServer:{ proxy:"http://localhost:5000" } 說明: 優點:配置簡單,請求資源時直接發給前端(8080)即可。 缺點:不能配置多個代理,不能靈活的控制請求是否 ...
  • 獲取微信昵稱、頭像、OpenID 微信公眾號服務號的網頁授權功能開發,主要是通過js跳轉到一個微信提供的url 然後微信會彈出獲取昵稱頭像的按鈕 允許獲取後,會回跳到我們的網址上,並且帶著一個code參數 我們拿到code參數,調用介面獲取到獲取到昵稱頭像、以及openid。這樣就拿到了微信客戶的主 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...