C++;性能模板? 我在网上看到过几次,提到C++可以更快地使用模板。

C++;性能模板? 我在网上看到过几次,提到C++可以更快地使用模板。,c++,templates,c++11,C++,Templates,C++11,有人能解释一下,包括在低层次上,这到底是为什么吗?我一直认为这样一个“好”的特性会像最有用的概念一样有开销 从超低延迟的角度来看,我对此非常感兴趣 > P>我不确定你是否在谈论C++模板元编程:在编译时做一些计算,这样你几乎可以在运行时立即得到结果。 如果是这样,下面是一个例子 通过使用模板元编程和模板专门化为递归提供结束条件,程序中使用的阶乘(忽略任何未使用的阶乘)可以通过此代码在编译时计算 template <int N> struct Factorial { enum

有人能解释一下,包括在低层次上,这到底是为什么吗?我一直认为这样一个“好”的特性会像最有用的概念一样有开销


从超低延迟的角度来看,我对此非常感兴趣

> P>我不确定你是否在谈论C++模板元编程:在编译时做一些计算,这样你几乎可以在运行时立即得到结果。 如果是这样,下面是一个例子

通过使用模板元编程和模板专门化为递归提供结束条件,程序中使用的阶乘(忽略任何未使用的阶乘)可以通过此代码在编译时计算

template <int N>
struct Factorial 
{
    enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
    int x = Factorial<4>::value; // == 24
    int y = Factorial<0>::value; // == 1
}
模板
结构阶乘
{
枚举{value=N*阶乘::值};
};
模板
结构阶乘
{
枚举{值=1};
};
//阶乘::值==24
//阶乘::值==1
void foo()
{
int x=阶乘::值;//==24
int y=阶乘::值;//==1
}
这里还有一点要读

他们最有可能谈论的是模板元编程,这是编译速度与运行速度之间的权衡。基本的想法是你可以编写一个程序,它将在C++编译器中执行。例如(从维基百科偷来的):

模板
结构阶乘
{
枚举{value=N*阶乘::值};
};
模板
结构阶乘
{
枚举{值=1};
};
//阶乘::值==24
//阶乘::值==1
void foo()
{
int x=阶乘::值;//==24
int y=阶乘::值;//==1
}
因此,要计算
Factorial::value
,编译器需要“展开”模板并计算
Factorial::value
等等。这一切都是在编译时完成的,这显然会增加编译时间,但会在运行时有效地用一个常量值替换它。

“更快”取决于您将它与什么进行比较

模板完全由编译器评估,因此它们在运行时的开销为零。调用
Foo()
与调用
FooInt()
一样高效

因此,与依赖于在运行时完成更多工作(例如通过调用虚拟函数)的方法相比,模板确实可以更快。与为该场景精确编写的手写代码相比,没有什么不同


因此,模板的好处不在于它们比其他方法“更快”,而在于它们与手写代码“一样快”,同时具有通用性和可重用性。

一个常见的例子是排序

在C语言中,
qsort
获取指向比较函数的指针。一般来说,将有一个
qsort
代码的副本,它不是内联的。它将通过指向比较例程的指针进行调用——这当然也不是内联的

在C++中,<>代码> STD::排序是模板,它可以将一个函子对象作为比较器。对于用作比较器的每种不同类型,都有一个不同的
std::sort
。假设您使用的函子类重载了
操作符()
,那么对比较器的调用可以很容易地内联到
std::sort
的这个副本中

因此,模板提供了更多的内联,因为有更多的
sort
代码副本,每个副本都可以内联不同的比较器。内联是一个很好的优化,排序例程做了很多比较,因此您可以经常测量
std::sort
运行速度比等效的
qsort
快。这样做的代价是可能产生更大的代码——如果您的程序使用许多不同的比较器,那么您会得到许多排序例程的不同副本,每个副本都有一个不同的比较器

原则上,C实现没有理由不能将
qsort
内联到调用它的位置。然后,如果使用函数名调用它,优化器在理论上可以观察到,在使用它时,函数指针必须仍然指向同一个函数。然后它可以内联调用函数,结果将类似于
std::sort
的结果。但在实践中,编译器往往不采取第一步,即内联
qsort
。这是因为(a)它很大,(b)它在一个不同的翻译单元中,通常编译到你的程序所链接的某个库中,(c)这样做的话,每次调用它都会有一个
qsort
的内联副本,而不仅仅是每个不同比较器的副本。因此,它将比C++更臃肿,除非实现在相同代码的不同位置调用“代码> qSeaS/<代码>的情况下,共同使用代码。 因此,C中的通用函数,如
qsort
,由于通过函数指针或其他间接[*]调用,往往会有一些开销。在C++中模板是一种常见的保持源代码通用性的方法,但确保它编译成专用函数(或几个这样的函数)。希望专用代码更快

值得注意的是,模板绝不仅仅是性能问题<在某些方面,code>std::sort本身比
qsort
更通用。例如,
qsort
仅对数组进行排序,而
std::sort
可以对提供随机访问迭代器的任何内容进行排序。例如,它可以对一个
deque
进行排序,它的封面下是几个单独分配的不相交数组。因此,使用模板并不一定会带来任何性能上的好处,可能是出于其他原因。碰巧模板确实会影响性能

[*]另一个排序示例-
qsort
采用一个整数参数,表示h
template <int N>
struct Factorial 
{
    enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
    int x = Factorial<4>::value; // == 24
    int y = Factorial<0>::value; // == 1
}
void qsort ( void * base, size_t num, size_t size, 
             int ( * comparator ) ( const void *, const void * ) );
template <class RandomAccessIterator, class StrictWeakOrdering>
void sort(RandomAccessIterator first, RandomAccessIterator last,
                StrictWeakOrdering comp);
vector<1000> a = foo(), b = bar(), c = baz(), result;
result = a + b + c;
for(int i = 0; i < 1000; ++i) {
    result[i] = a[i] + b[i] + c[i];
}