C++学习1

RVO:

complex.h 中

operator + (const complex& x, const complex& y)

{
  return complex (real (x) + real (y), imag (x) + imag (y));

}

compex_test.cpp中

complex c3 = c1 + c2;

此处编译器 有一个 返回值优化,本来应该有一个构造函数,复制构造函数,析构函数的开销,但此处直接按值返回编译器将只有一个 构造函数的开销。

如果进行了优化,那就不会发生对象拷贝行为,等号左边那个变量会引用那个临时对象。这个对象的生命周期结束于等号左右的两个东西的生命周期都结束的时候。

参考

http://www.cnblogs.com/xkfz007/archive/2012/07/21/2602110.html


左值右值:

c 语言中,通常来说有名字的变量就是左值,而由运算操作(加减乘除,函数调用返回值等)所产生的中间结果(没有名字)就是右值

在 c++ 中,每一个表达式都会产生一个左值,或者右值,相应的,该表达式也就被称作“左值表达式", "右值表达式"。对于内置的基本数据类型来说(primitive types),左值右值的概念和 c 没有太多不同,不同的地方在于自定义的类型,而且这种不同比较容易让人混淆:

1) 对于内置的类型,右值是不可被修改的(non-modifiable),也不可被 const, volatile 所修饰(cv-qualitification ignored)

2) 对于自定义的类型(user-defined types),右值却允许通过它的成员函数进行修改。

自定义类型允许有成员函数,而通过右值调用成员函数是被允许的,但成员函数有可能不是 const 类型,因此通过调用右值的成员函数,也就可能会修改了该右值

右值不能当成左值使用(但左值可以当成右值使用).右值特性:

1) 允许调用成员函数。

2) 只能被 const reference 指向。(延长生存周期和RVO有内在联系 )

参考

http://www.cnblogs.com/catch/p/3500678.html


inline 关键字:

函数调用需要时间和空间开销,调用函数实际上将程序执行流程转移到被调函数中,被调函数的代码执行完后,再返回到调用的地方。这种调用操作要求调用前保护好现场并记忆执行的地址,返回后恢复现场,并按原来保存的地址继续执行。对于较长的函数这种开销可以忽略不计,但对于一些函数体代码很短,又被频繁调用的函数,就不能忽视这种开销。引入内联函数正是为了解决这个问题,提高程序的运行效率。

在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。由于在编译时将内联函数体中的代码替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间开销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。


◆使用宏的缺点:(1)容易出错(预处理器在复制宏代码时常常产生意想不到的边际效应)
                  例如:#define MAX(a,b)    (a) > (b) ? (a) : (b)
                        语句result = MAX(i,j) + 2 却被扩展为result = (i)>(j)?(i):(j)+2;
                        但意却为result = ((i)>(j)?(i):(j)) + 2;
              (2)不可调试
              (3)无法操作类的私有数据成员

        C++函数内联机制既具备宏代码的效率,又增加了安全性,且可自由操作类的数据成员。
        关键字inline必须与函数定义体放在一起才能使函数真正内联,仅把inline放在函数声明的前面不起任何作用。因为inlin是一种用于实现的关键字,不是一种用于声明的关键字。
(1) 在一个文件中定义的内联函数不能在另一个文件中使用。它们通常放在头文件中共享。
(2) 内联函数应该简洁,只有几个语句,如果语句较多,不适合于定义为内联函数。 
(3) 内联函数体中,不能有循环语句、if语句或switch语句,否则,函数定义时即使有inline关键字,编译器也会把该函数作为非内联函数处理。
(4) 内联函数要在函数被调用之前声明。
参考

http://www.cnblogs.com/li-hao/archive/2013/03/15/2961713.html

初始化列表:

构造函数的执行可以分成两个阶段,初始化阶段和计算阶段,初始化阶段先于计算阶段。

所有类类型(class type)的成员都会在初始化阶段初始化,即使该成员没有出现在构造函数的初始化列表中。

对于内置类型,如int, float等,使用初始化类表和在构造函数体内初始化差别不是很大,但是对于类类型来说,最好使用初始化列表,使用初始化列表少了一次调用默认构造函数的过程,这对于数据密集型的类来说,是非常高效的。使用初始化列表只调用一次拷贝构造函数。

除了性能问题之外,有些时场合初始化列表是不可或缺的,以下几种情况时必须使用初始化列表

1.需要初始化的数据成员是对象(继承时调用基类构造函数)
2.需要初始化const修饰的类成员

3.需要初始化引用成员数据


const对象或引用只能初始化但是不能赋值。构造函数的函数体内只能做赋值而不是初始化,因此初始化const对象或引用的唯一机会是构造函数函数体之前的初始化列表中。


如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数

初始化列表执行顺序是根据在类中定义的顺序初始化的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值