说个题外话
#include <iostream>
using namespace std;
class A
{
public:
char a;
char b;
char c;
public:
A(char aa, char bb=97, char cc=97):a(aa),b(bb),c(cc){}
};
int main()
{
A e=98;
cout<<e.a<<e.b<<e.c<<endl;
return 0;
}
对于 下面的 A e= 98; 是能够匹配到A的构造函数的,aa 需不需要默认值都可以,这样的声明会将 98 赋予第一个 参数,即aa 。
主要内容:
class Rational
{
friend Rational operator +(const Rational &,const Rational &);
public:
Rational(int a=0,int b=1):m(a),n(b){}
private:
int m;
int n;
};
对于对象定义:
Rational r1(100);
Rational r2 = Rational(100);
Rational r3= 100;
只有第一个r1 是不会创建临时变量的,另外两个都会。不过编译器优化了,所以3者效率一样。
对于类型不匹配:
Rational r;
r=100;
这样第二句会寻找Ratiaonal 的构造函数(如我上面写的那个题外话),然后再调用拷贝函数实现。
想禁止这用转换,可以再构造函数(对于其他什么函数都适用)前面加explicit
class Rational
{
public:
explicit Rational(int a=0, int b=1):m(a),n(b){}
};
有时候调用函数时会产生临时变量的,如
void g(const string &s){}
g("message");
下面的调用函数中传递的是指针。
再按例子 Complex类
complex a,b;
for(int i=0;i<100;i++)
{
a= i*b +1.0;
}
complex a,b;
complex one(1,0);
for(int i=0;i<100;i++)
{
a= i*b +one;
}
上面部分中的1.0 需要不断的创建于销毁。
按值传递:
一般的调用:
T t;
g(t);
编译器将需要创建T 类型的临时对象,并且用t 作为输入参数调用拷贝构造函数创建这个变量,然后以这个变量作为实参传递给个g(),然后返回时调用析构函数释放临时变量。
按值返回:
调用函数会创建变量保存返回值,如果有赋值语句就调用赋值函数,最后是释放临时变量。
通过上一章可以消除在被调用函数中的临时变量 (RVO)。
至于消除当前函数的临时变量。就要考虑。
对于语句 s3=s1 +s2. 源函数会产生一个临时变量保存 s1+s2 的值。为什么会产生呢?
这是两个操作 ,+ = ,对于s1+s2 部分没有权利修改s3 的值。(这是 = 的是功能)。
如果s3 有旧值时,不能将s3 作为这一临时变量,但如果s3 是新声明的,便能直接作为该变量,这样就省了一个临时变量。
写法:
//有临时变量
string s1= "Hello ";
string s2= "World ";
string s3;
s3=s1+s2;
//无临时变量
string s1= "Hello ";
string s2= "World ";
string s3=s1+s2;
至于在s3 有旧值的情况下,可以这样来避免创建临时变量。
//有临时变量
string s1,s2,s3,s4;
s1=s2+s3+s4;
//无临时变量
s1=s2;
s1+=s3;
s1+=s4;
要点:
1.临时对象会以构造函数和析构函数的形式降低一半的性能。
2.将构造函数声明为 explicit,可以阻止编译器幕后使用类型转换。
3.编译器常常创建临时对象来解决类型不匹配问题。通过重载可以避免这种情况。
4.如果肯尼个,尽量避免使用对象拷贝(应该指函数调用的时候),按引用传递和返回对象。
5.在
原文链接: https://www.cnblogs.com/Azhu/archive/2012/07/14/2591555.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/55178
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!