Tôi nghĩ bạn hiểu nhầm cách thức triển khai mẫu. Các mẫu được biên dịch trên cơ sở cần sử dụng vào một lớp/chức năng tương ứng.
Xét đoạn mã sau ...
template <typename Type>
Type mymax(Type a, Type b) {
return a > b ? a : b;
}
int main(int argc, char** argv)
{
}
Biên soạn này, tôi nhận được lắp ráp sau.
.file "example.cpp"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1"
.section .note.GNU-stack,"",@progbits
Bạn sẽ nhận thấy nó chỉ chứa chức năng chính. Bây giờ tôi cập nhật mã của tôi để sử dụng chức năng mẫu.
int main(int argc, char** argv)
{
mymax<double>(3,4);
}
Biên dịch rằng tôi nhận được kết quả lắp ráp dài hơn bao gồm chức năng mẫu để xử lý tăng gấp đôi. Trình biên dịch thấy chức năng mẫu đã được sử dụng bởi kiểu "double" để tạo ra một hàm để xử lý trường hợp đó.
.file "example.cpp"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movabsq $4616189618054758400, %rdx
movabsq $4613937818241073152, %rax
movq %rdx, -24(%rbp)
movsd -24(%rbp), %xmm1
movq %rax, -24(%rbp)
movsd -24(%rbp), %xmm0
call _Z5mymaxIdET_S0_S0_
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.section .text._Z5mymaxIdET_S0_S0_,"axG",@progbits,_Z5mymaxIdET_S0_S0_,comdat
.weak _Z5mymaxIdET_S0_S0_
.type _Z5mymaxIdET_S0_S0_, @function
_Z5mymaxIdET_S0_S0_:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movsd %xmm0, -8(%rbp)
movsd %xmm1, -16(%rbp)
movsd -8(%rbp), %xmm0
ucomisd -16(%rbp), %xmm0
jbe .L9
movq -8(%rbp), %rax
jmp .L6
.L9:
movq -16(%rbp), %rax
.L6:
movq %rax, -24(%rbp)
movsd -24(%rbp), %xmm0
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size _Z5mymaxIdET_S0_S0_, .-_Z5mymaxIdET_S0_S0_
.ident "GCC: (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1"
.section .note.GNU-stack,"",@progbits
Bây giờ, hãy thay đổi mã để sử dụng chức năng đó hai lần.
int main(int argc, char** argv)
{
mymax<double>(3,4);
mymax<double>(4,5);
}
Một lần nữa, hãy nhìn vào hội đồng mà nó tạo ra. Nó có thể so sánh với đầu ra trước đó vì hầu hết mã đó chỉ là trình biên dịch tạo hàm mymax trong đó "Loại" được thay đổi thành gấp đôi. Dù tôi sử dụng chức năng đó bao nhiêu lần, nó sẽ chỉ được khai báo một lần.
.file "example.cpp"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movabsq $4616189618054758400, %rdx
movabsq $4613937818241073152, %rax
movq %rdx, -24(%rbp)
movsd -24(%rbp), %xmm1
movq %rax, -24(%rbp)
movsd -24(%rbp), %xmm0
call _Z5mymaxIdET_S0_S0_
movabsq $4617315517961601024, %rdx
movabsq $4616189618054758400, %rax
movq %rdx, -24(%rbp)
movsd -24(%rbp), %xmm1
movq %rax, -24(%rbp)
movsd -24(%rbp), %xmm0
call _Z5mymaxIdET_S0_S0_
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.section .text._Z5mymaxIdET_S0_S0_,"axG",@progbits,_Z5mymaxIdET_S0_S0_,comdat
.weak _Z5mymaxIdET_S0_S0_
.type _Z5mymaxIdET_S0_S0_, @function
_Z5mymaxIdET_S0_S0_:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movsd %xmm0, -8(%rbp)
movsd %xmm1, -16(%rbp)
movsd -8(%rbp), %xmm0
ucomisd -16(%rbp), %xmm0
jbe .L9
movq -8(%rbp), %rax
jmp .L6
.L9:
movq -16(%rbp), %rax
.L6:
movq %rax, -24(%rbp)
movsd -24(%rbp), %xmm0
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size _Z5mymaxIdET_S0_S0_, .-_Z5mymaxIdET_S0_S0_
.ident "GCC: (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1"
.section .note.GNU-stack,"",@progbits
Vì vậy, các mẫu cơ bản không ảnh hưởng đến kích thước thực thi nhiều hơn viết chức năng bằng tay. Nó chỉ là một tiện lợi. Trình biên dịch sẽ tạo ra một hàm cho một hoặc nhiều cách sử dụng của một kiểu đã cho nên nếu tôi sử dụng nó 1 hoặc 1000 lần, sẽ chỉ có một thể hiện của nó.Bây giờ nếu tôi cập nhật mã của mình để xử lý một kiểu mới như float, tôi sẽ nhận được một hàm khác trong tệp thực thi của mình, nhưng chỉ một hàm bất kể tôi sử dụng hàm đó bao nhiêu lần.
Họ không. (Mặc dù họ có thể làm một số coalescing cho cùng một loại) Đó là lý do tại sao nó có thể sụp đổ một trình biên dịch C + + với một vài dòng mã mẫu cẩn thận bằng văn bản. – Mysticial
Điều gì làm cho bạn nghĩ rằng họ làm gì? –
Việc khởi tạo mẫu lớp sẽ xuất hiện trong exe của bạn một lần, cho dù bạn đã tạo một phiên bản của nó bao nhiêu lần. Cùng với các mẫu chức năng. Bạn không nhận được một thực thi lớn chỉ vì bạn đã khai báo 1000 biến loại vector. –
polkadotcadaver