11

据我了解,例如,如果您有 anstd::vector<int>和 an std::vector<float>,编译器会创建两个类,每种类型一个。因此,尽管您减少了编写的代码量,但并没有减少可执行文件的大小(如果我错了,请纠正我)。

即使类型是指针也一样吗?例如,实例化 anstd::vector<SomeClass*>和 anstd::vector<SomeOtherClass*>必然会导致编译器为两个实例中的每一个生成单独的代码吗?

4

5 回答 5

6

这是一个依赖于实现的模拟优化,因此是允许的!

事实上,这甚至不必由编译器完成。标准库可以这样实现。例如,一个实现可以使用std::is_pointer然后将所有内容推迟到一个基于单个void*的实现。(这是薄模板成语)。事实上,在库端这样做似乎比编译器在实例化后合并代码更可行,但这也是可能的。

于 2012-12-17T12:53:11.497 回答
5

编译器从模板中实例化与您的程序使用的一样多的类。但是,生成到可执行文件中的代码与程序中存在哪些类略有不同。

在实践中,大多数操作vector都是内联的。因此,可执行文件大小可能不会根据从该模板实例化的不同类的数量而发生很大变化,因为大部分代码大小是每个函数调用站点而不是每个不同的类。但就它而言,它取决于实例化的数量,vector<SomeClass*>并且vector<SomeOtherClass*>是不同的类。

如果您对 进行显式实例化vector,则将为该类生成所有成员函数。如果您寻找它,您可能会看到代码大小的差异。但通常您不会显式实例化模板类,因此只会生成您使用的成员函数。

于 2012-12-17T12:28:01.647 回答
4

允许编译器生成一组代码来实现模板的两个实例化,前提是生成的行为是正确的。这可能发生在指针类型和非指针类型上。它可以为模板类中的每个例程(又名“方法”)独立发生。

可能很难确定何时会发生这种情况,编译器可能会也可能不会意识到这样做的机会。

例如,如果例程仅复制一个类,就像赋值运算符通常所做的那样,那么可以将相同的代码用于类数据具有相同大小的模板的任何实例化。在某些处理器上,添加两个int对象的代码可能与添加到对象的代码相同。unsigned int

于 2012-12-17T12:34:03.037 回答
4

你是对的。有一些方法可以减少重复,请参阅我的饮食模板演示文稿中的幻灯片 18-26。

有一点是“常识”,std::vector<T*>它们std::vector<U*>都可以作为围绕vector_impl<void*>专业化的薄包装器来实现,因此它们尽可能共享相同的生成代码(这就是我在幻灯片中所说的提升),但我不认为现代 std::lib 实现实际上进行了优化。当然 libstdc++ 没有。

于 2012-12-17T12:57:25.047 回答
2

编译器不会“创建两个类”。相反,std::vector<int>std::vector<float> 两个不同的类。不要混淆类和模板——它们是语言的核心概念!同样,std::vector<SomeClass *>andstd::vector<SomeOtherClass *>是两个不同的类,应该可以回答您的问题。

于 2012-12-17T12:20:13.290 回答