读《深度探索C++对象模型》之对象成员的效率

测试平台:华硕N53S(五年前的老机子)

编译环境:VS2010

接下来我将会有多个测试,在多个不同环境下的所消耗的时间比较:

五个测试分别为:个别的局部变量、局部数组、struct之的Public、class 之中的inline Get函数、 class之中的inline Get & Set函数:

代码片段如下:

struct Point
{
	Point(float mx, float my, float mz)
	{
		x = mx; y = my; z = mz;
	}
	float x, y, z;
};

class Point3D
{
public:
	Point3D(float xx = 0.0f, float yy = 0.0f, float zz = 0.0f)
		:_x(xx), _y(yy), _z(zz)
	{

	}

	float &x () {return _x;}
	float &y () {return _y;}
	float &z () {return _z;}

	void x(float nx) {_x = nx;}
	void y(float ny) {_y = ny;}
	void z(float nz) {_z = nz;}

private:
	float _x, _y, _z;
};

int main()
{
	double dur;
	clock_t start, end;
	//local
	float pA_x = 1.725f, pA_y = 0.875f, pA_z = 0.478f;
	float pB_x = 0.315f, PB_y = 0.317f, PB_z = 0.838f;
	start = clock();
	for (unsigned i = 0; i < 100000000; ++i)
	{
		pB_x = pA_x - PB_z;
		PB_y = pA_y - pB_x;
		PB_z = pA_z - PB_y;
	}
	end = clock();
	dur = double(end - start);
	printf("Use time 1 : %f\n", (dur/CLOCKS_PER_SEC));
	//
	enum fussy{x, y, z};
	float pA[3] = {1.725f, 0.875f, 0.478f};
	float pB[3] = {0.315f, 0.317f, 0.838f};
	start = clock();
	for (unsigned i = 0; i < 100000000; ++i)
	{
		pB[x] = pA[x] - pB[z];
		pB[y] = pA[y] + pB[x];
		pB[z] = pA[z] + pB[y];
	}
	end = clock();
	dur = double(end - start);
	printf("Use time 2 : %f\n", (dur/CLOCKS_PER_SEC));

	Point sPa(1.725f, 0.875f, 0.478f);
	Point sPb(0.315f, 0.317f, 0.838f);
	start = clock();
	for (unsigned i = 0; i < 100000000; ++i)
	{
		sPb.x = sPa.x - sPb.z;
		sPb.y = sPa.y + sPb.x;
		sPb.z = sPa.z + sPb.y;
	}
	end = clock();
	dur = double(end - start);
	printf("Use time 3 : %f\n", (dur/CLOCKS_PER_SEC));

	Point3D cpA(1.725f, 0.875f, 0.478f);
	Point3D cpB(0.315f, 0.317f, 0.838f);
	start = clock();
	for (unsigned i = 0; i < 100000000; ++i)
	{
		cpB.x() = cpA.x() - cpB.z();
		cpB.y() = cpA.y() + cpB.x();
		cpB.z() = cpA.z() + cpB.y();
	}
	end = clock();
	dur = double(end - start);
	printf("Use time 4 : %f\n", (dur/CLOCKS_PER_SEC));

	Point3D cpA1(1.725f, 0.875f, 0.478f);
	Point3D cpB1(0.315f, 0.317f, 0.838f);
	start = clock();
	for (unsigned i = 0; i < 100000000; ++i)
	{
		cpB1.x(cpA1.x() - cpB1.z());
		cpB1.y(cpA1.y() + cpB1.x());
		cpB1.z(cpA.z() + cpB.y());
	}
	end = clock();
	dur = double(end - start);
	printf("Use time 5 : %f\n", (dur/CLOCKS_PER_SEC));

	system("pause");
	return 0;
}

在不打开如何优化的时间下,所用的时间如下:

可以看出,在不优化的情况下,前面三种几乎时间是一样的,因为可以说是C的用法,后面两种是C++的用法,所消耗的时间几乎是前两种的2倍,应该是由于封装所带来的时间吧。下面在打卡vs2010的全部优化开关的情况下所用的时间:

可以看到,在优化全部打开的情况下,五种情况下的时间,基本上都为1.165ms,类所带来的封装也就没有带来什么执行期的效率成本了。

那如果加上继承呢,那我们再次来验证一下:

单一的继承:

优化的情况下:

未优化的情况下:

虚拟继承(单一)(指的是Point2d虚拟继承于Point1d):

优化的情况下:

未优化的情况下:

在多层的虚拟继承情况下呢:

优化的情况下:

未优化的情况下:

可以看到,对于虚拟继承来说,所消耗的时间会比较多些,可能是因为我的测试比较简单,不是很明显。

所以能不用虚拟继承,就不要用吧,除非没办法了。

时间: 2024-11-02 20:35:16

读《深度探索C++对象模型》之对象成员的效率的相关文章

《深度探索c++对象模型》chapter1关于对象对象模型

在c++中,有2种class data member:static和nostatic,以及3钟class member function:static,nostatic和virtual.已知下面这个class Point声明: class Point { public: Point(float xval); virtual ~Point(); float x() const; static int PointCount(); protected: virtual ostream& print(o

【深度探索C++对象模型】第一章 关于对象

第一章 关于对象(Object Lessons) -- 本书作者:Stanley B.Lippman 一.前言 什么是 C++ 对象模型:简单的说,就是 C++ 中面向对象的底层实现机制. 本书组织: 第 1 章,关于对象(Object Lessons),介绍 C++ 对象的基础概念,给读者一个粗略的了解. 第 2 章,构造函数语意学(The Semantics of Constructors),构造函数什么时候会被编译器合成?它给我们的程序效率带来了怎样的影响? 第 3 章,Data语意学(T

[读书系列] 深度探索C++对象模型 初读

2012年底-2014年初这段时间主要用C++做手游开发,时隔3年,重新拿起<深度探索C++对象模型>这本书,感觉生疏了很多,如果按前阵子的生疏度来说,现在不借助Visual Studio之类的工具的话,写C++代码感觉要比较费劲,最近重读了这本书后,感觉要写点东西下来(因为懒得用笔作笔记,太慢了-_-!)加深下印象. 以前还是新手的时候,总是认为: 1.class如果没有定义任何constructor的话,编译器会自动合成一个default constructor(我习惯叫缺省的构造函数)出

柔性数组-读《深度探索C++对象模型》有感 (转载)

最近在看<深度探索C++对象模型>,对于Struct的用法中,发现有一些地方值得我们借鉴的地方,特此和大家分享一下,此间内容包含了网上搜集的一些资料,同时感谢提供这些信息的作者. 原文如下: 例如,把单一元素的数组放在一个struct的尾端,于是每个struct objects可以拥有可变大小的数组.    code: struct mumble { //stuff char pc[1];    };        //从档案或标准输入装置中取得一个字符串,然后为struct本身和该字符串配置

深度探索C++对象模型 第五章 构造、析构、拷贝语意学

1. const 成员函数需要吗? 尽量不要,如果存在继承,则无法预支子类是否有可能改变data member 2. pure virtual constructor 可以实现类的隐藏吗(包含data member)?   这样子类无法调用base 的构造函数对数据初始化,所以可以用protected来实现构造函数,可以实现子类调用: 3. 如果class中存在virtual function,则编译器会再构造函数中对vptr进行初始化(在base构造函数调用之后,而代码实现之前) 4.拷贝构造

深度探索C++对象模型 第二章构造函数语意学

在使用C++时,常常会好奇或者抱怨,编译器为我们做了什么事呢? 为什么构造函数没有为我初始化呢?为什么我还要写默认构造函数呢? 2.1 Default Constructor 的构造操作 如果没有声明默认构造函数,编译器会在需要的时候帮我们产生出来. 为了避免在多个地方被需要导致重复,则编译器将产生的构造函数声明为inline方式. class Foo {public:Foo(), Foo(int) }; class Bar {public: Foo foo;char *str;} Bar ba

深度探索C++对象模型的读书心得

参考:深度探索C++对象模型 (stanley B.Lippman著 侯捷翻译) 1. Page9 : C++对象模型,说明每一个类仅有一个虚函数表Vtbl,而类的每一个对象都有指向其表的指针. 2. Page30:引用也需要与一个指针(大小为4BYTE)相同的空间. 3. Page28: 指针类型会教导编译器如何解释某个特定地址中的内存内容及大小. 4. Page39: explicit关键字能够制止"单一参数的constructor被当做一个Conversion运算符" 5. Pa

【深度探索C++对象模型】第二章 构造函数语意学(上)

第二章 构造函数语意学(The Semantics of Constructors) -- 本书作者:Stanley B.Lippman 一.前言 首先让我们来梳理一个概念: 默认构造函数(Default Constructor) : 是在没有显示提供初始化式时调用的构造函数.它由不带任何参数的构造函数,或是为所有形参提供默认实参的构造函数定义.如果定义的某个类的成员变量没有提供显示的初始化式时,就会调用默认构造函数(Default Contructor). 如果用户的类里面,没有显示的定义任何

深度探索C++对象模型第6章 执行期语意学

(一)对象的构造和析构(Object Construction and Destruction) 一般而言我们会把object尽可能放置在使用它的那个程序区段附近,这么做可以节省非必要的对象产生操作和摧毁操作. 全局对象 如果我们有以下程序片段: Matrix identity main() { //identity 必须在此处被初始化 Matrix m1=identity; ... return 0; } C++保证,一定会在main()函数中第一次用到identity之前,把identity

【深度探索c++对象模型】Function语义学之虚函数

虚函数的一般实现模型:每一个class有一个virtual table,内含该class之中有作用的virtual function的地址,然后每个object有一个vptr,指向virtual table. 识别class是否支持多态,唯一恰当的方法是看它是否有virtual function,只要class拥有virtual function,它就需要额外的执行期信息. 考虑ptr->z(),ptr是基类指针,z是虚函数,为了找到并调用z()的适当实体,我们需要两项信息: 1.ptr所指对象