C++ 中的模板参数存储在哪里?
Where are template parameters stored in c++?
假设我们有一个 class A:
template<int N>
class A final{
public:
void foo() const { cout << N << endl; }
};
模板参数N存放在哪里?在堆中还是在栈中对象的内存中?
N
本身不存储在任何地方,它被编码到类型中。从这个角度来看,模板特化 A<1>
与非模板 class A1
相同。对于 A<2020>{}.foo()
,您可能会得到与 std::cout << 2020
相同的程序集。当然,常量 2020
必须存储在某个地方,但它不会成为 A<2020>{}
对象的一部分。
编译后,根据目标架构,A<2020>{}.foo()
可能如下所示 (x86-64):
mov esi, 2020
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
这里N
直接放入寄存器
或(ARM):
ldr r1, .L4
ldr r0, .L4+4
bl std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
...
.L4:
.word 2020
.word _ZSt4cout
此处N
是从某个内存位置加载的。
一般来说,使用模板的好处是模板本身不会消耗任何 运行 时间的性能,也不会在 运行 时间消耗内存 space。它们甚至在 运行 时不再存在,因为它们已经在编译时被完全处理和评估。
因此,模板本身成本性能和 space 唯一的时间是在编译时。
但是,模板在编译时生成的代码当然会在 运行 时花费 space。如果模板被实例化多次,那么代码也会生成多次,程序使用的每一组模板参数都会生成一次。代码大小的增加也会对性能产生负面影响,因为 CPU 指令缓存可以比大量代码更好地缓存少量代码。
回答你的问题:
在运行时,模板本身和它们的参数既不存储在堆上也不存储在堆栈上,因为它们甚至不存在了。只有在编译时,模板及其参数才会存储在编译器的堆或堆栈中的某个位置。但是,您对编译器的内部结构不感兴趣(除非您打算编写自己的编译器)。
但是,在您的示例中,问题中 N 的值仍将存储在程序中的某个位置。但它不会存储为模板参数,而是作为在编译时评估模板的结果存储在程序的可执行代码中的立即值。它有时实际上也可能存储在程序的堆栈中,因为在您的示例中,它作为函数调用的参数传递。但是,函数参数是通过堆栈传递还是通过 CPU 寄存器传递取决于您使用的平台。
假设我们有一个 class A:
template<int N>
class A final{
public:
void foo() const { cout << N << endl; }
};
模板参数N存放在哪里?在堆中还是在栈中对象的内存中?
N
本身不存储在任何地方,它被编码到类型中。从这个角度来看,模板特化 A<1>
与非模板 class A1
相同。对于 A<2020>{}.foo()
,您可能会得到与 std::cout << 2020
相同的程序集。当然,常量 2020
必须存储在某个地方,但它不会成为 A<2020>{}
对象的一部分。
编译后,根据目标架构,A<2020>{}.foo()
可能如下所示 (x86-64):
mov esi, 2020
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
这里N
直接放入寄存器
或(ARM):
ldr r1, .L4
ldr r0, .L4+4
bl std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
...
.L4:
.word 2020
.word _ZSt4cout
此处N
是从某个内存位置加载的。
一般来说,使用模板的好处是模板本身不会消耗任何 运行 时间的性能,也不会在 运行 时间消耗内存 space。它们甚至在 运行 时不再存在,因为它们已经在编译时被完全处理和评估。
因此,模板本身成本性能和 space 唯一的时间是在编译时。
但是,模板在编译时生成的代码当然会在 运行 时花费 space。如果模板被实例化多次,那么代码也会生成多次,程序使用的每一组模板参数都会生成一次。代码大小的增加也会对性能产生负面影响,因为 CPU 指令缓存可以比大量代码更好地缓存少量代码。
回答你的问题:
在运行时,模板本身和它们的参数既不存储在堆上也不存储在堆栈上,因为它们甚至不存在了。只有在编译时,模板及其参数才会存储在编译器的堆或堆栈中的某个位置。但是,您对编译器的内部结构不感兴趣(除非您打算编写自己的编译器)。
但是,在您的示例中,问题中 N 的值仍将存储在程序中的某个位置。但它不会存储为模板参数,而是作为在编译时评估模板的结果存储在程序的可执行代码中的立即值。它有时实际上也可能存储在程序的堆栈中,因为在您的示例中,它作为函数调用的参数传递。但是,函数参数是通过堆栈传递还是通过 CPU 寄存器传递取决于您使用的平台。