【问题标题】:Code reuse (or not) in C++ templatesC++ 模板中的代码重用(或不重用)
【发布时间】:2015-10-19 10:49:34
【问题描述】:

到目前为止,在我读过的所有书籍中,他们都说 C++ 模板会为我们使用的每种类型生成一个代码实例。

另一方面,书上说在 C# 中代码是可重用的。

所以我在很多书籍中进行了搜索,我在一本非常古老的书中找到了以下 C# 示例。

1) 值类型

List<int> intList1  = new List<int>();
List<int> intList2  = new List<int>();
List<bool> boolList = new List<bool>();

在这种情况下(值类型),编译器为 intList1 和 intList2(相同类型)生成一个代码实例,为 boolList 生成一个代码实例。

2) 引用类型

List<Dog> dogList1 = new List<Dog>();
List<Dog> dogList2 = new List<Dog>();
List<Cat> catList  = new List<Cat>();

在这种情况下(引用类型),编译器只为 dogList1、dogList1 和 catList 生成一个代码实例,因为只要它可以表示指向对象的指针,所有引用类型都可以共享一个实现。

这对我来说很清楚(作为 C++ 开发人员),但我对有关 c++ 模板的同样事情感到好奇。

早在 C# 创建之前,C++ 也有值类型和引用类型。

让我们用 C++ 重写前面的例子

1) 值类型

vector<int> intList1;
vector<int> intList2;
vector<bool> boolList;

在这种情况下,我毫不怀疑 intList1 和 intList2 共享相同的代码,而 boolList 需要另一个实现

2) 引用类型

vector<Dog *> dogList1;
vector<Dog *> dogList2;
vector<Cat *> catList;

我的问题是:

我能否得出结论,在第二种情况下(指针向量),只要所有向量指针(vector 和 vector)都共享相同的模板实例化并且所有指针的大小相同(32 位还是 64 位取决于平台)?

【问题讨论】:

  • 它是特定于实现的。请注意,C++11 有 extern template
  • “C++ 也有值类型和引用类型”——“值”和“引用”类型之间没有区别。您可以拥有指向int 的指针,并且可以使用Dog 作为值。
  • 对我来说,这个问题应该被称为“二进制”重用。
  • 这不是很多实现定义的吗? AFAIK 语言标准对二进制表示的假设很少......
  • 指针不是引用类型。 C++ 没有(也从未有过,也永远不会有)C# 中已知的“引用类型”。此外,C++ 模板与 C# 泛型有很大不同。

标签: c++ templates


【解决方案1】:

(您的问题有些混乱,但让我跳过这一点并解决实际问题)。

不,你不能假设。

这主要是因为无论您的系统是 32 位还是 64 位,指针不一定必须具有相同的大小。

【讨论】:

  • 这可能是一个很好的信息补充:stackoverflow.com/q/6751749/1147772
  • @Bathsheba:«在 32 位 Windows 上,整数、长整数和指针数据类型的大小都相同——32 位。数据类型大小的这种方便的统一性对聪明的 C 程序员来说是一个福音,他们中的许多人已经认为这是理所当然的。然而,在 64 位 Windows 上,这种统一性假设不再有效。指针现在的长度为 64 位,但整数和长数据类型的大小与以前相同——32 位。» msdn.microsoft.com/en-us/library/ff565649%28v=vs.85%29.aspx
【解决方案2】:

或许,您可以使用静态变量来检查这一点,如下所示:

#include <iostream>
using namespace std;

template <typename T>
class Wrapper
{
public:
    static int count;
    T d_wrapped;

    Wrapper(T i_wrap) : d_wrapped(i_wrap)
    {
        ++count;
    }
};

template <typename T>
int Wrapper<T>::count = 0;

int main() {
    Wrapper<int> wi(1);
    Wrapper<int> wi2(2);
    Wrapper<float> wf(1.0f);

    Wrapper<int*> wip(new int());
    Wrapper<float*> wfp(new float());

    cout << Wrapper<int>::count << ' ' << Wrapper<float>::count << '\n' <<
            Wrapper<int*>::count << ' ' << Wrapper<float*>::count << '\n';
    return 0;
}

Ideone live code

在 ideone 上发布表明,即使对于指针,我们也有单独的静态变量。

【讨论】:

  • 这是一种有趣的检查方式,但如果static存在,编译器可能会压缩代码。
猜你喜欢
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 2017-07-16
  • 1970-01-01
相关资源
最近更新 更多