实施例: 假设我包含在我的预编译头文件中:
#include <vector>
由于矢量的一些实例,例如std :: vector,std :: vector等经常在我的项目中使用,如果我在预先插入的头文件中实例化它们会减少编译时间,如下所示:
#include <vector>
template class std::vector<float>;
template class std::vector<int>;
更进一步,甚至将伪函数添加到使用一些函数的预编译头文件中是否有意义:
namespace pch_detail {
inline auto func() {
auto&& v = std::vector<float>{};
v.size();
v.begin();
v.front();
}
}
我非常不确定翻译单元和模板是如何工作的,所以在我看来,如果我在预编译的头文件中实例化它们,它应该意味着它们不需要为每个.cpp文件实例化它们
更新
使用Visual Studio 2017测试真实代码库以及常用模板类的一些实例。
因此,至少在我的情况下,需要花费更多时间。
答案 0 :(得分:4)
有趣的是,但至少对于clang
(4.0.1),你的变量会增加编译时间:
1. no pch
real 0m0,361s
user 0m0,340s
sys 0m0,021s
2. pch, no explicit instantiate
real 0m0,297s
user 0m0,280s
sys 0m0,017s
3. pch, explicit instantiate
real 0m0,507s
user 0m0,474s
sys 0m0,033s
我使用这样的代码:
#include <iostream>
#include "test.h"
int main() {
std::vector<float> a = {1., 2., 3.};
for (auto &&e : a) {
std::cout << e << "\n";
}
std::vector<int> b = {1, 2, 3};
for (auto &&e : b) {
std::cout << e << "\n";
}
}
案例2 test.h
#pragma once
#include <vector>
案例3
#pragma once
#include <vector>
template class std::vector<float>;
template class std::vector<int>;
和这样的编译脚本:
echo "no pch"
time clang++ -std=c++11 main.cpp
echo "pch, no explicit instantiate"
clang++ -std=c++11 -x c++-header test.h -o test.pch
time clang++ -std=c++11 -include-pch test.pch main.cpp
echo "pch, explicit instantiate"
clang++ -std=c++11 -x c++-header test2.h -o test2.pch
time clang++ -std=c++11 -include-pch test2.pch main2.cpp
答案 1 :(得分:3)
它可以有所作为。
翻译单元中的实例化可以利用预编译头中的数据,编译器可以比C ++标准库头更快地读取它。
但是你必须维护一个实例化列表,所以这个编译时优化可能比它的价值更麻烦 - 如果你有不再需要的实例化,你的想法可能会产生相反的效果
答案 2 :(得分:1)
我也在考虑这种方式,我也有这个问题。 (但我是否......)
另一个参考:https://msdn.microsoft.com/en-us/library/by56e477.aspx
可能需要明确extern
吗?
但是,当需要链接时,cpp文件已编译为.obj
,但.pch
不是.obj
...
然后,模板函数的实例化将在哪里?链接器是否能够从.pch
?
或者我们需要另一个专门用于实例化它们的.cpp
,同时将所有客户端引用声明为extern
?
并且..链接时代码生成?
它有点工作。使用VS2012进行测试。打开编译器分析并观察编译器输出。
// stdafx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <deque>
// stdafx.cpp
#include "stdafx.h"
using namespace std;
template class set<int>;
template set<int>::set();
template set<int>::_Pairib set<int>::insert(const int&);
template class deque<int>;
template deque<int>::deque();
template void deque<int>::push_back(const int&);
template class vector<int>;
template vector<int>::vector();
template void vector<int>::push_back(const int&);
// playcpp.cpp, the entry point
#include "stdafx.h"
using namespace std;
// toggle this block of code
// change a space in the "printf", then build (incrementally)
/*
extern template class set<int>;
extern template set<int>::set();
extern template set<int>::_Pairib set<int>::insert(const int&);
extern template class deque<int>;
extern template deque<int>::deque();
extern template void deque<int>::push_back(const int&);
extern template class vector<int>;
extern template vector<int>::vector();
extern template void vector<int>::push_back(const int&);
*/
int _tmain(int argc, _TCHAR* argv[])
{
set<int> s;
deque<int> q;
vector<int> v;
for(int i=0;i<10000;i++){
int choice=rand()%3;
int value=rand()%100;
switch(choice){
case 0: s.insert(value); break;
case 1: q.push_back(value); break;
case 2: v.push_back(value); break;
}
}
for(const auto &i:s)
printf("%d",i);
for(const auto &i:q)
printf("%d ",i);
for(const auto &i:v)
printf("%d ",i);
return 0;
}
结果(许多其他遗漏)
使用extern声明:
1> 1630 毫秒 Build 1 次调用
...
1> 757 毫秒 ClCompile 1 次调用
1> 787 毫秒 Link 1 次调用
没有外部声明:
1> 1801 毫秒 Build 1 次调用
...
1> 774 毫秒 Link 1 次调用
1> 955 毫秒 ClCompile 1 次调用
(中文版。传说:毫秒:ms /毫秒,x次调用:x调用/调用x次)
调整功率设置以使CPU运行缓慢,以便获得更长的时间以避免湍流。
上面只是每个案例的一个样本。它仍然很不稳定。两种情况有时可能会持续约200ms。
但是多次尝试,在平均上总是有大约200毫秒的差异。我可以说平均值大约是1650毫秒和1850毫秒,而且在ClCompile的时间里差别很大。
当然还有更多调用其他模板成员函数,只是我没有时间弄清楚所有那些类型的签名......(谁能告诉我它将使用哪个(const)迭代器? )
那么,那么....有更好的方法吗?