函數模板 模板的意義:對類型也參數化 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
函數模板是無法編譯的,也不進行編譯的,函數模板在調用點發生模板實例化動作,被實例化化後 成為模板函數,模板函數才是真正參與編譯的
關於模板特例化
如果有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
template bool compare
2:加模板聲明寫在頭文件中,在調用點文件include 進來