12

一些缺点是

  1. 它的语法很复杂
  2. 编译器生成额外代码
4

11 回答 11

26

它们很难验证。不被使用的模板代码往往很少被编译。因此,良好的测试用例覆盖率是必须的。但是测试很耗时,然后可能会证明代码从一开始就不需要健壮。

于 2010-04-29T06:07:41.890 回答
24

嗯,怎么样...

3:它们编译起来可能很慢

4:它们强制在编译时而不是运行时计算事物(如果您更喜欢快速执行速度而不是运行时灵活性,这也是一个优势)

5:较旧的 C++ 编译器不处理它们,或者不能正确处理它们

6:当你没有得到正确的代码时,它们产生的错误信息几乎是不可理解的

于 2010-04-29T05:44:33.343 回答
12

模板将您的实现暴露给代码的客户端,如果您在库边界传递模板化对象,这会使维护 ABI 变得更加困难。

于 2010-04-29T06:05:18.433 回答
11

到目前为止,似乎没有人提到我发现模板的主要缺点:代码可读性直线下降!

我指的不是语法问题——是的,语法很丑,但我可以原谅。我的意思是:我发现对于以前从未见过的非模板代码,无论应用程序有多大,如果我从头开始,main()我通常可以毫无问题地解码程序正在执行的大致步骤。仅使用vector<int>或类似的代码丝毫不会打扰我。但是,一旦代码开始定义和使用自己的模板来实现简单容器类型之外的目的,可理解性很快就会消失。 这对代码维护有非常负面的影响。

其中一部分是不可避免的:模板通过复杂的偏序重载解析规则(对于函数模板)以及在较小程度上的偏特化(对于类模板)提供了更大的表达性。但是规则非常复杂,即使是编译器编写者(我很高兴承认他们比我聪明一个数量级)在极端情况下仍然会弄错。

C++ 中命名空间、友元、继承、重载、自动转换和参数相关查找的交互已经足够复杂了。但是,当您将模板添加到组合中时,以及它们附带的名称查找和自动转换规则的细微变化时,复杂性可能会达到我认为没有人可以处理的程度。我只是不相信自己能够阅读和理解使用所有这些结构的代码。


与模板无关的一个困难是调试器仍然难以自然地显示 STL 容器的内容(与 C 风格的数组相比)。

于 2010-04-29T06:40:55.570 回答
10

唯一真正的缺点是,如果您在模板中犯了任何微小的语法错误(尤其是其他模板使用的语法错误),则错误消息将无济于事……期待几页几乎无法使用的错误消息;-)。编译器的缺陷是非常特定于编译器的,语法虽然丑陋,但并不真正“复杂”。总而言之,尽管正确的错误诊断存在巨大问题,但模板仍然C++ 中最好的东西,这很可能会诱使您使用 C++ 而不是其他泛型实现较差的语言,例如 Java ...

于 2010-04-29T05:45:11.080 回答
4

编译器解析它们很复杂,这意味着您的编译时间会增加。如果您有高级模板结构,也很难解析编译器错误消息。

于 2010-04-29T05:45:19.223 回答
3

了解它们的人越来越少,尤其是在元编程层面,因此能够维护它们的人也越来越少。

于 2010-04-29T17:24:12.053 回答
2

当您使用模板时,您的编译器只会生成您实际使用的内容。我认为使用 C++ 模板元编程没有任何缺点,除了编译时间可能会很长,如果你使用像 boost 或 loki 库那样非常复杂的结构。

于 2010-04-29T06:40:33.417 回答
1

一个缺点:模板错误只有在模板被实例化时才会被编译器检测到。有时,模板的方法中的错误仅在成员方法被实例化时才被检测到,而不管模板的其余部分是否被实例化。

如果我在模板类的方法中有错误,只有一个函数引用,但其他代码使用没有该方法的模板,编译器将不会生成错误,直到错误的方法被实例化。

于 2010-04-29T17:17:13.833 回答
1

最糟糕的情况:您从错误的模板代码中获得的编译器错误消息。

于 2010-04-29T17:21:47.810 回答
0

多年来,我有时会使用模板。它们可能很方便,但从专业的角度来看,我正在远离它们。其中两个原因是:

1.

需要 a.) 将函数定义(不仅是声明)“源”代码公开给“使用位置”代码,或者 b.) 在源文件中创建一个虚拟实例化。这是编译所需要的。选项 a.) 可以通过在头文件中定义函数或实际包含 cpp 来完成。

我们容忍 C++ 中的标头(例如与 C# 相比)的原因之一是因为“接口”与“实现”的分离。好吧,模板似乎与这种哲学不一致。

2.

模板类型参数实例化调用的函数可能不会在编译时强制执行,从而导致链接错误。例如 T 示例;example.CompilerDoesntKnowIfThisFunctionExistsOnT(); 这是“松散的”恕我直言。

解决方案:

我倾向于使用基类,而不是模板,派生/容器类可以在编译时知道什么是可用的。基类可以提供模板常用的通用方法和“类型”。这就是为什么如果需要修改现有代码以在需要的继承层次结构中插入通用基类,源代码可用性会很有帮助。否则,如果代码是封闭源代码,则使用通用基类更好地重写它,而不是使用模板作为解决方法。

If type is unimportant e.g. vector< T > then how about just using"object". C++ has not provided an "object" keyword and I have proposed to Dr. Bjarne Stroustrup that this would be helpful especially to tell compiler and people reading code that type is not important (for cases when it isn't). I don't that think C++11 has this, perhaps C++14 will?

于 2014-07-12T19:45:17.583 回答