模板类是否C++使用的每种指针类型复制代码
Do C++ template classes duplicate code for each pointer type used?
据我了解,例如,如果您有std::vector<int>
和std::vector<float>
,编译器会创建两个类,每种类型一个。因此,尽管您减少了编写的代码量,但不会减少可执行文件的大小(如果我错了,请纠正我)。
即使类型是指针,情况也一样吗?例如,实例化std::vector<SomeClass*>
和std::vector<SomeOtherClass*>
是否必然会导致编译器为这两个实例化中的每一个生成单独的代码?
这是一个依赖于实现的假设优化,因此是允许的!
事实上,这甚至不必由编译器完成。标准库可以通过这种方式实现。例如,实现可以使用std::is_pointer
,然后将所有内容推迟到单个基于 void*
的实现。(这是瘦模板习语)。事实上,在库端执行此操作似乎比编译器在实例化代码后合并代码更可行,但这也是可能的。
模板实例化程序使用的类数。但是,为在可执行文件中生成的代码与程序中存在的类略有不同。
实际上,vector
上的大多数操作都将内联。因此,可执行文件大小可能不会根据从该模板实例化的不同类的数量而发生太大变化,因为代码大小的大部分是每个函数调用站点而不是每个不同的类。但就它取决于实例化的数量而言,vector<SomeClass*>
和vector<SomeOtherClass*>
是不同的类。
如果你显式实例化vector
,那么所有的成员函数都将为该类生成。如果您寻找它,您可能会看到代码大小的差异。但通常不会显式实例化模板类,因此仅生成您使用的成员函数。
编译器生成一组代码来实现模板的两个实例化,前提是生成的行为是正确的。指针类型和非指针类型可能会发生这种情况。它可以针对模板类中的每个例程(也称为"方法")独立发生。
可能很难确定何时会发生这种情况,并且编译器可能会也可能不会识别这样做的机会。
例如,如果例程只是复制一个类,就像赋值运算符通常所做的那样,那么可以对类数据具有相同大小的模板的任何实例化使用相同的代码。在某些处理器上,添加两个int
对象的代码可能与添加到unsigned int
对象的代码相同。
是的,你是对的。有一些方法可以减少重复,请参阅我的饮食模板演示文稿中的幻灯片 18-26。
有一点是"常识",std::vector<T*>
和std::vector<U*>
都可以作为围绕vector_impl<void*>
专业化的薄包装器实现,因此它们在可能的情况下共享相同的生成代码(这就是我在幻灯片中所说的提升),但我不认为现代 std::lib 实现实际上可以进行这种优化。当然libstdc++没有。
编译器不会"创建两个类"。相反,std::vector<int>
和std::vector<float>
是两个不同的类。不要混淆类和模板——它们是语言的核心概念!同样,std::vector<SomeClass *>
和std::vector<SomeOtherClass *>
是两个不同的类,它们应该回答你的问题。
- C++中的双指针类型转换
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 将类指针类型转换为键时出错
- 错误:表达式必须具有算术、无作用域枚举或带有运算符重载的指针类型
- C++在一个映射中存储不同的指针类型(并处理销毁)
- 指针类型类成员的动态强制转换的恒定性是什么?
- 我正在尝试将表的地址传递给要在另一个函数中使用的指针,但得到不兼容的指针类型
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- STL 函数和函数类型与函数指针类型
- 如何调用指针类型的方法(禁用多态性)?
- 为什么新表达式可以正确生成指针类型,即使它应该返回 void*?
- 对于非常量指针类型的参数,未调用具有常量指针模板类型参数的功能
- 是否允许调用方对我的 Builder 类使用任何指针类型(包括智能指针)?
- OPENCL 警告:不兼容的指针类型将'float __global[16]'传递给类型为 '__global float4 的参数 *
- 专门用于"direct"函数类型(与函数指针类型相对)
- 指向成员的指针类型和模板
- 返回对常量结构(指针类型)成员的引用:明显的左值到右值转换
- 在C++17中,为什么类模板和函数模板的指针类型推导明显不一致
- 为什么允许将整型、枚举和指向成员的指针类型reinterpret_cast到自身?