【问题标题】:Avoid inlining of explcitly instantiated std::vector<T> code? (Visual Studio C++ 2008)避免内联显式实例化的 std::vector<T> 代码? (Visual Studio C++ 2008)
【发布时间】:2012-01-24 09:37:31
【问题描述】:

我想在我正在处理的大型项目中减小 .obj 文件的大小(我知道链接器会删除重复的定义,但我想加快构建过程)。它们大小的原因之一是每个使用std::vector&lt;double&gt;std::vector&lt;std::string&gt; 的类最终都会编译该类的代码并将其放置在其.obj 文件中。我尝试显式实例化std::vector&lt;double&gt; 并使用extern template 声明,但它不起作用——Visual Studio C++ STL 中的std::vector 具有内联的所有方法。除了修改 STL 代码(我不会这样做),有什么方法可以强制编译器不要内联实例化方法并使用 std::vector&lt;double&gt; 的外部实例化版本?

【问题讨论】:

  • 微软的C++编译器什么时候支持extern template了?据我所知,它只是被忽略了。
  • 不是。我在 VS 2008(带有 SP1)上尝试过它并且它有效。

标签: c++ visual-studio-2008 templates stl build


【解决方案1】:

唯一想到的是编写一个包含标头,该标头定义 std::vector 模板(但不是它的成员,只需要声明)并包含它而不是 vector 标准标头。

然后您可以在单独的编译单元中显式实例化 std::vector&lt;whatever&gt; 并链接到它。

要显式实例化模板,请不要使用extern template(这不起作用),只需使用以下内容:

#include <vector> // The standard header, not your forward-declaration!

template class std::vector<double>;

【讨论】:

  • @quant_dev 忘了我说的吧,它可能会起作用(但你的实验表明它不起作用,在这种情况下)。再说一次,没有extern 的实例化也是如此。
  • 是的,当模板在类定义中不包含方法定义时,它可以工作。
  • 但是——如果我只是向前声明std::vector,要调用它的方法我需要包含&lt;vector&gt;,然后游戏就结束了。
  • @quant_dev 不,如果您在另一个编译单元中显式实例化模板(该编译单元除外),则不需要包含 &lt;vector&gt;。这很好用,我在两天前使用了同样的技术。
  • @quant_dev 另外,工作选择错误:你需要在转发头中定义std::vector,这是真的。你不需要定义它的成员,声明它们就足够了。
【解决方案2】:

我现在的建议是hack,因为它对代码进行卷积以实现编译器优化。在您尝试此操作之前,应调查编译器标志。

总而言之,编译器放入 obj 文件的内容取决于编译器,但我建议尝试继承向量的特殊化,并使用这种特殊化。我可以想象这将使编译器创建一个包含向量特化的 obj 文件,从而允许包装向量的所有用户使用它。

【讨论】:

    【解决方案3】:

    除非您更改 vector 标头或提供仅包含声明的等效项,否则它不可能这样做。否则,每当您 #include 文件 vector 时,它的内容都会进入包含文件并被编译,并且模板在第一次使用时被实例化。然后链接器消除重复项。这就是 C++ 编译的工作原理,你不能在这里做任何事情。

    【讨论】:

    • 不完全一样。如果模板类在类定义中不包含方法定义,那么我可以在类定义之后添加extern template 声明,编译器避免在使用点实例化模板,信任extern template 声明。让我受益的是方法的内联。
    猜你喜欢
    • 1970-01-01
    • 2017-03-13
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多