c++ - 'instantiation' 对模板的意义

标签 c++ templates

Note that code is instantiated only for member functions that are called. For class templates, member functions are instantiated only when they are used.



上面的引文来自这本书:Addison Wesley 的 C++ Templates。

我想了解行话“代码被实例化”的含义。这是否意味着只保留特定的内存,或者只编译该代码或其他什么?

最佳答案

这是一个非常有趣的问题,应该在编译器如何处理模板的更广泛的上下文中完成。基本上模板是编译器从中生成函数类的代码模式。模板可用于生成从根本没有代码(如果从未使用过)到无限数量的实例化的任何内容。

模板不会被直接编译成稍后与不同参数一起使用的任何实体短(在 C# 泛型中是这样,但在 C++ 中不是),而是代码由编译器解析并保存在内存中,以防以后使用处理当前翻译单元。也就是说,编译器处理模板(斜体模板用于创建事物的模式的英文形式,而不是精确的 C++ 含义),它将在需要时从中创建代码(类或函数)。实例化是编译器确定特定模板与特定参数集一起使用并对模板执行参数替换以生成要编译的类或函数并最终编译为模板的二进制代码的过程。

模板实例化有两种类型,隐式和显式,您引用的引用是关于隐式模板实例化的。我将从显式模板实例化开始,因为它更简单。当您显式实例化一个模板(语法在 google 上)时,您告诉编译器您希望从该模板生成的代码应用于您提供的特定参数。在类模板的情况下,这会强制实例化所有成员函数,这基本上意味着编译器将替换类型并将其结果编译为二进制对象。

另一方面,隐式实例化是按需执行的。当您使用类模板时,实际使用的零碎部分从模板生成并编译到翻译单元中。如果创建变量定义 std::vector<int> v; ,编译器将应用类型 int (和默认类型 std::allocator<int> )到 template std::vector并创建一个类型 std::vector<int> ,但这样做时,它不会编译所有成员函数,而只会编译那些需要的函数,在这种情况下,它将是默认构造函数 std::vector<int>::vector() , 和析构函数 std::vector<int>::~vector() .其余的方法不会被编译,二进制文件中不会有它们的代码。

没有实例化所有成员函数有几个原因,原因从复杂到语言细节从简单到深入。对于一些更简单的,您可以考虑编译性能(不必仅仅因为使用其中一个成员函数就必须生成/编译所有成员函数将大大减少编译时间)。稍微复杂一点的是,模板中的不同成员函数可能对实例化类型施加不同的要求。例如,operator[]map要求值的类型是默认可构造的,因为如果 map 中不存在,运算符将创建一个新元素,另一方面,如果您总是使用 findinsert ,您可以使用 std::map具有不可默认构造的类型。通过不强制编译所有成员函数,该语言允许您使用带有不满足所有方法的所有要求的参数的模板,只要它满足实际使用的那些方法的要求。

我在上面的描述中使用了相当多的术语,但我还没有定义它。对于一个精确的定义,你必须去标准,但你可以认为使用成员函数是一个很好的近似,如果它是从你的代码中直接或间接调用的(即你调用它,或者你调用它的其他一些成员函数)实例化调用它)或者如果您获得成员函数的地址。

关于c++ - 'instantiation' 对模板的意义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7304696/

相关文章:

c++ - if constexpr - 为什么完全检查丢弃的语句?

c++ - 将 native WebRTC 应用程序与 Visual Studio 链接

c++ - 从 C++ 中的字符串中删除双引号

c++ - uniform_int_distribution <> 和 <int> 有什么区别?

c++ - 模拟模板化构造函数。太奇怪了?

c++ - 枚举变量作为动态模板参数

c++ - 当 T 没有复制构造函数时,std::queue<T> 的虚拟包装器不编译

c++ - 具有 lambda 的多态访问者

c++ - 如何解决这个歧义?

c++ - C++ 中的继承和模板