就提高程序的性能/效率而言,上层的平台/架构/算法/数据结构当然重要,然而也不能忽视代码本身的性能优化,即为了让编译器将你写的高级语言的代码翻译成尽量高效的机器代码,这方面也是我很感兴趣的领域,下面就记录一些improve performance of c++ codes的方方面面,希望从点滴做起,写出相对高效的c++codes。
条款1:
--------------------------------
Q:构造函数中使用初始化列表(Initialization list)还是赋值(Aassignment)来初始化成员?
A:尽量使用初始化列表。
--------------------------------
测试:
--------------------------------
(测试主要集中于在x86平台上的MS编译器,且是在开启编译器的最大优化功能的情况下,一般对应Release模式)
下面看个c++ test program:
//TestClass.h
class A
{
public:
A();
int i;
};
//TestClass.cpp
#include "TestClass.h"
A::A()
{
i = 0;
}
//LGVector.h
#include "TestClass.h"
class LGVector
{
public:
// constructor
LGVector(){};
LGVector(A a);
private:
int i;
A a;
};
//LGVector.cpp
#include "TestClass.h"
// Initializaton list
LGVector::LGVector(A a) : a(a)
{
}
// Assignment
//LGVector::LGVector(A a) : a(a)
//{
// a = a;
//}
//main.cpp
#include "LGVector.h"
int main(int argc, char* argv[])
{
A a1;
a1.i = 10;
LGVector v1(a1);
return 0;
}
下面是LGVector构造函数的x86 Assembly codes:
初时化列表:(x86, VC++ 6.0, Release, Optimization: Maximize)
_a$ = 8
??0LGVector@@QAE@VA@@@Z PROC NEAR ; LGVector::LGVector, COMDAT
; 14 : {
mov eax, ecx
mov ecx, DWORD PTR _a$[esp-4] // 不会调用A的构造函数
mov DWORD PTR [eax+4], ecx
; 15 : }
ret 4
赋值操作:(x86, VC++ 6.0, Release, Optimization: Maximize)
_a$ = 8
??0LGVector@@QAE@VA@@@Z PROC NEAR ; LGVector::LGVector, COMDAT
; 7 : {
push esi
mov esi, ecx
push edi
lea edi, DWORD PTR [esi+4]
mov ecx, edi
call ??0A@@QAE@XZ ; A::A // 会调用A的构造函数,注意:并没有分配额外的内存来创
建额外的对象,只是将当前对象的的子对象a的指针(edi)传递到A:A()中,做一些初时化。performance的下降只在于A:A()的调用。
; 8 : this->a = a;
mov eax, DWORD PTR _a$[esp+4]
mov DWORD PTR [edi], eax
; 9 : }
mov eax, esi
pop edi
pop esi
ret 4
--------------------------------
小结:
--------------------------------
VC++ 6.0下:
在构造函数中,推荐使用初时化列表来初始化成员,可以避免成员的构造函数的调用,提高performance,但只针对
non built-in/instinctive types,因为built-in/instinctive types没有构造函数。
在VC++2005:
貌似两者performance一样,赋值操作来初始化成员也不会调用成员的构造函数。
--------------------------------
条款1:
--------------------------------
Q:构造函数中使用初始化列表(Initialization list)还是赋值(Aassignment)来初始化成员?
A:尽量使用初始化列表。
--------------------------------
测试:
--------------------------------
(测试主要集中于在x86平台上的MS编译器,且是在开启编译器的最大优化功能的情况下,一般对应Release模式)
下面看个c++ test program:
//TestClass.h
class A
{
public:
A();
int i;
};
//TestClass.cpp
#include "TestClass.h"
A::A()
{
i = 0;
}
//LGVector.h
#include "TestClass.h"
class LGVector
{
public:
// constructor
LGVector(){};
LGVector(A a);
private:
int i;
A a;
};
//LGVector.cpp
#include "TestClass.h"
// Initializaton list
LGVector::LGVector(A a) : a(a)
{
}
// Assignment
//LGVector::LGVector(A a) : a(a)
//{
// a = a;
//}
//main.cpp
#include "LGVector.h"
int main(int argc, char* argv[])
{
A a1;
a1.i = 10;
LGVector v1(a1);
return 0;
}
下面是LGVector构造函数的x86 Assembly codes:
初时化列表:(x86, VC++ 6.0, Release, Optimization: Maximize)
_a$ = 8
??0LGVector@@QAE@VA@@@Z PROC NEAR ; LGVector::LGVector, COMDAT
; 14 : {
mov eax, ecx
mov ecx, DWORD PTR _a$[esp-4] // 不会调用A的构造函数
mov DWORD PTR [eax+4], ecx
; 15 : }
ret 4
赋值操作:(x86, VC++ 6.0, Release, Optimization: Maximize)
_a$ = 8
??0LGVector@@QAE@VA@@@Z PROC NEAR ; LGVector::LGVector, COMDAT
; 7 : {
push esi
mov esi, ecx
push edi
lea edi, DWORD PTR [esi+4]
mov ecx, edi
call ??0A@@QAE@XZ ; A::A // 会调用A的构造函数,注意:并没有分配额外的内存来创
建额外的对象,只是将当前对象的的子对象a的指针(edi)传递到A:A()中,做一些初时化。performance的下降只在于A:A()的调用。
; 8 : this->a = a;
mov eax, DWORD PTR _a$[esp+4]
mov DWORD PTR [edi], eax
; 9 : }
mov eax, esi
pop edi
pop esi
ret 4
--------------------------------
小结:
--------------------------------
VC++ 6.0下:
在构造函数中,推荐使用初时化列表来初始化成员,可以避免成员的构造函数的调用,提高performance,但只针对
non built-in/instinctive types,因为built-in/instinctive types没有构造函数。
在VC++2005:
貌似两者performance一样,赋值操作来初始化成员也不会调用成员的构造函数。
--------------------------------