代码之家  ›  专栏  ›  技术社区  ›  hidayat

C++中的问题理解模板

  •  5
  • hidayat  · 技术社区  · 14 年前

    在使用模板函数之前,不会编译模板代码。但是它在哪里保存编译后的代码,它是否保存在最初使用模板函数的对象文件中?

    例如, cpp正在从文件test.h调用模板函数,编译器生成一个对象文件main.o, 模板函数是否在主.o文件中?因为模板代码不是内联的,是吗?

    5 回复  |  直到 14 年前
        1
  •  4
  •   Klaim    14 年前

    它完全依赖于编译器实现。大多数编译器都会围绕、内联或类似cpp的文件生成代码,然后用这些代码进行编译。有时,通过优化设置,一些编译器甚至会重用相同的代码,而不是为每个cpp重新创建它。

    所以你必须查看你的编译器的文档来获得更多的细节。

        2
  •  3
  •   Michael Ekstrand    14 年前

    是的,模板函数代码在 main.o 文件。其中一些代码可能是内联的,就像任何其他代码可能是内联的一样,但是通常,模板的代码是在模板所在的任何文件中发出的。 实例化 . 把它看作首先实例化模板代码以生成普通的非模板函数,然后用编译器应用于任何其他函数的任何内联和优化来编译这些函数。

    当相同的模板实例化(例如 std::vector<int> )在多个编译单元中发生( .cpp 文件),这有点困难,因为代码在每个文件中都是实例化的。处理这个问题的方法有很多种,有时涉及到链接阶段的一个清理步骤,其中重复的模板实例化被解析为一个单独的模板实例化;编译器手册可以提供更多关于它如何处理这种情况的信息。

        3
  •  1
  •   sbi    14 年前

    模板代码 即使它从未被实例化,也会被编译。否则,不需要编译器对此发出诊断:

    template< typename T >
    void f()
    {
      blah
    }
    

    模板编译发生在 两相 . 除了基本检查之外,依赖于模板参数的所有内容都只能在实例化模板并用实际类型填充形式参数时进行检查。例如,这里

    template< typename T >
    void f()
    {
      typename T::nested_type x;
    }
    

    T::nested_type 只有在模板被实例化并为给定了实际类型之后才能检查 T . 但是,一个基本的检查 T::嵌套类型 是类型,这是有效的变量定义吗?”)在编译器遇到模板定义时执行。(这就是为什么 typename 是必需的,顺便说一句,取决于 T , T::嵌套类型 也可能是 T 或者一个静态数据成员 T::nested_type x; 语法错误。所以我们必须告诉编译器 T::嵌套类型 作为类型的名称。)

        4
  •  0
  •   Francesco larlin    14 年前

    你的意思是实例化的,而不是编译的。在编译时,编译器会找出代码使用的每个版本,并(在对象文件中)设置所有必需的版本。

        5
  •  0
  •   Pavel Radzivilovsky    14 年前

    它总是内联的(意思是,它总是内部链接,具有内联语义)。它实际上可能根本就不是内联的,就像内联函数一样,但是模板不是代码。它是一个“代码模板”。因此,它通常位于头文件中,特殊情况除外,见下文。

    有一个想法,使其他东西,代号为“导出关键字”。它已从标准中删除。

    特殊情况:可以编译 模板实例化 放入一个对象文件中,而不使用它们。这是避免所有模板代码内联的唯一方法。 就是这样做的:

    template class std::vector<MyClass>;
    

    这将强制编译器在当前位置实例化模板。C++ 0x将有一个强制编译器的语法 要执行此操作,并让链接器在其他地方搜索模板实例化:

    extern template class std::vector<MyClass>; // C++0x only