笔记列表 
《提高C++性能的编程技术》笔记:总结 
《提高C++性能的编程技术》笔记:跟踪 
《提高C++性能的编程技术》笔记:构造函数、析构函数 
《提高C++性能的编程技术》笔记:临时对象 
《提高C++性能的编程技术》笔记:内存池(单线程、多线程) 
《提高C++性能的编程技术》笔记:内联 
《提高C++性能的编程技术》笔记:STL 
《提高C++性能的编程技术》笔记:引用计数 
《提高C++性能的编程技术》笔记:编码优化 
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构 
虚函数:在以下几个方面,虚函数可能会造成性能损失:构造函数必须初始化vptr(虚函数表);虚函数是通过指针间接调用的,所以必须先得到指向虚函数表的指针,然后再获得正确的函数偏移量;内联是在编译时决定的,编译器不可能把运行时才解析的虚函数设置为内联。
无法内联虚函数造成的性能损失最大。
某些情况下,在编译期间解析虚函数的调用是可能的,但这是例外情况。由于在编译期间不能确定所调用的函数所属的对象类型,所以大多数虚函数调用都是在运行期间解析的。编译期间无法解析对内联造成了负面影响。由于内联是在编译期间确定的,所以它需要具体函数的信息,但如果在编译期间不能确定将调用哪个函数,就无法使用内联。
评估虚函数的性能损失就是评估无法内联该函数所造成的损失。这种损失的代价并不固定,它取决于函数的复杂程度和调用频率。一种极端情况是频繁调用的简单函数,它们是内联的最大受益者,若无法内联则会造成重大性能损失。另一极端情况是很少调用的复杂函数。
通过对类选择进行硬编码或者将它作为模板参数来传递,可以避免使用动态绑定。
因为函数调用的动态绑定是继承的结果,所以消除动态绑定的一种方法是用基于模板的设计来替代继承。模板把解析的步骤从运行期间提前到编译期间,从这个意义上说,模板提高了性能。而对于我们所关心的编译时间,适当增加也是可以接受的。
返回值优化:通过转换源代码和消除对象的创建来加快源代码的执行速度,这种优化称为返回值优化(Return Value Optimization, RVO)。
编译器优化要保证原来计算的正确性。然而对于RVO来说,这一点并不总是易于实现的。既然RVO不是强制执行的,编译器就不会对复杂的函数执行RVO。例如,如果函数有多个return语句返回不同名称的对象,这样就不会执行RVO。如果想使用RVO,就必须返回相同名称的对象。
当编译器无法执行RVO时,可按计算性构造函数的形式来实现。
如果必须按值返回对象,通过RVO可以省去创建和销毁局部对象的步骤,从而改善性能。
RVO的应用要遵照编译器的实现而定。这需要参考编译器文档或通过实验来判断是否使用RVO以及何时使用。
通过编写计算性构造函数可以更好地使用RVO。
以下是测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 #include  <iostream>  #include  <chrono>    namespace  return_value_optimization_ {    class  Complex  {	friend  Complex operator  + (const  Complex&, const  Complex&); 	friend  void  Complex_Add (const  Complex&, const  Complex&, Complex&)  	friend  Complex Complex_Add2 (const  Complex&, const  Complex&)  	friend  Complex Complex_Add3 (const  Complex&, const  Complex&)    public :	Complex (double  r =0.0 , double  i =0.0 ) : real (r), imag (i) {}  	Complex (const  Complex& c) : real (c.real), imag (c.imag) {}  	Complex (const  Complex& a, const  Complex& b) : real (a.real + b.real), imag (a.imag + b.imag) {}  	Complex& operator  = (const  Complex& c) { this ->real = c.real; this ->imag = c.imag; return  *this ; } 	~Complex () {}   private :	double  real; 	double  imag;   };   Complex operator  + (const  Complex& a, const  Complex& b) { 	Complex retVal; 	retVal.real = a.real + b.real; 	retVal.imag = a.imag + b.imag;   	return  retVal; }   void  Complex_Add (const  Complex& a, const  Complex&b, Complex& __tempResult) 	__tempResult.real = a.real + b.real; 	__tempResult.imag = a.imag + b.imag; }   Complex Complex_Add2 (const  Complex& a, const  Complex& b)  	Complex retVal; 	retVal.real = a.real + b.real; 	retVal.imag = a.imag + b.imag;   	return  retVal; }   Complex Complex_Add3 (const  Complex& a, const  Complex& b)  	return  Complex (a, b); } }  using  namespace  return_value_optimization_;int  main () 	 	using  namespace  std::chrono; 	high_resolution_clock::time_point time_start, time_end; 	const  int  cycle_number {100000000 };   {  	Complex a (1 , 0 )  ; 	Complex b (2 , 0 )  ; 	Complex c;   	time_start = high_resolution_clock::now (); 	for  (int  i = 0 ; i < cycle_number; ++i) { 		c = a + b; 	} 	time_end = high_resolution_clock::now (); 	std::cout<<"common add time spend: " <<(duration_cast<duration<double >>(time_end - time_start)).count ()<<" seconds\n" ; }   {  	Complex a (1 , 0 )  ; 	Complex b (2 , 0 )  ; 	Complex c; 	 	time_start = high_resolution_clock::now (); 	for  (int  i = 0 ; i < cycle_number; ++i) { 		Complex_Add (a, b, c); 	} 	time_end = high_resolution_clock::now (); 	std::cout<<"RVO add time spend: " <<(duration_cast<duration<double >>(time_end - time_start)).count ()<<" seconds\n" ; }   	   {  	Complex a (1 , 0 )  ; 	Complex b (2 , 0 )  ; 	Complex c;   	time_start = high_resolution_clock::now (); 	for  (int  i = 0 ; i < cycle_number; ++i) { 		c = Complex_Add2 (a, b); 	} 	time_end = high_resolution_clock::now (); 	std::cout<<"common add time spend: " <<(duration_cast<duration<double >>(time_end - time_start)).count ()<<" seconds\n" ; }   {  	Complex a (1 , 0 )  ; 	Complex b (2 , 0 )  ; 	Complex c;   	time_start = high_resolution_clock::now (); 	for  (int  i = 0 ; i < cycle_number; ++i) { 		c = Complex_Add3 (a, b); 	} 	time_end = high_resolution_clock::now (); 	std::cout<<"计算性构造函数 add time spend: " <<(duration_cast<duration<double >>(time_end - time_start)).count ()<<" seconds\n" ;   }   	return  0 ; }     
利用 godbolt 执行,相应代码见 点击这里  测试结果如下:
1 2 3 4 common add time spend: 1.67e-07 seconds RVO add time spend: 5.6e-08 seconds common add time spend: 3.3e-08 seconds 计算性构造函数 add time spend: 3.5e-08 seconds