c++进阶(1)

对象使用过程中背后调用了哪些方法

实例代码1:(注意t4的构造)

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a = 10) :ma(a) { cout << "Test()" << endl; }
	~Test() { cout << "~Test()" << endl; }
	Test(const Test& t) :ma(t.ma) { cout << "Test(const Test&)" << endl; }
	Test& operator=(const Test& t)
	{
		cout << "operator=" << endl;
		ma = t.ma;
		return *this;
	}

private:
	int ma;

};


int main()
{
	Test t1;//普通构造
	Test t2(t1);//拷贝构造
	Test t3 = t1;//拷贝构造
	//Test(20)显示生产临时对象  生存周期:所在的语句
	Test t4 = Test(20);//普通构造  等价于 Test t4(20)
	return 0;
}

在这里插入图片描述
t4属于是c++编译器对于对象构造的优化,用临时对象生成新对象的时候,临时对象就不产生了,直接构造新对象就可以了

但如果是
t4 = Test(30);
那么首先会调用构造函数,构造一个临时对象,然后再通过赋值运算符重载
在这里插入图片描述
其次,临时对象在出了语句之后就会立马析构

对于t4 = (Test)30;// 把整数强转成Test类型,显示
编译器会看,Test有没有带int类型的构造函数
还有隐式构造
t4 = 30;

示例代码2:

//p指向的是临时对象
Test* p = &Test(40);

const Test& ref = Test(50);//引用不能变,所以加const
cout << "---------- " << endl;

上面一句是错误的,因为指向的是一个临时对象,出了语句以后就会析构,就没了

而下面可以,因为const起别名了,相当于给临时对象安了名字,生命周期就变了

示例代码3:

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a = 10,int b = 20) :ma(a) ,mb(b){ cout << "Test(int ,int)" << endl; }
	~Test() { cout << "~Test()" << endl; }
	Test(const Test& src) :ma(src.ma),mb(src.mb) { cout << "Test(const Test&)" << endl; }
	void operator=(const Test& src)
	{
		cout << "operator=" << endl;
		ma = src.ma;
		mb = src.mb;
	}

private:
	int ma;
	int mb;

};

Test t1(10, 10);//1 -- Test(int,int)

int a()
{
	Test t2(20, 20);//3 -- Test(int, int)
	Test t3 = t2;//4 -- Test(const Test&)
	static Test t4 = Test(30, 30);//5 -- Test(int,int)

	t2 = Test(40, 40);//6 -- Test(int,int) + operator= + ~Test()
	t2 = (Test)(50, 50);//7 -- (Test)50 ->Test(50,20) + operator= + ~Test()
	t2 = 60;//8 -- Test(int,int)+ operator= + ~Test()

	Test* p1 = new Test(70, 70);//9 -- Test(int,int)
	Test* p2 = new Test[2];//10 -- Test(int,int),Test(int,int)两次
	//Test* p3 = &Test(80, 80);//11 -- 不能用指针指向临时对象
	const Test& p4 = Test(90, 90);//12 -- Test(int,int)

	delete p1;//13 -- ~Test()释放p1 
	delete []p2;//14 -- ~Test(),~Test()两次
	return 0;
	//15 -- p4析构
	//16 -- p3析构
	//17 -- t3析构
	//18 -- t2析构
	//19 -- t4析构 --- static是在数据区
	//20 -- t5,t1析构 --- 全局区


}
Test t5(100, 100);//2 -- Test()

程序运行以后,首先是全局变量先构造
所以是t1先构造,其次是t5,之后就是按顺序

static Test t4 = Test(30, 30);中,存在编译器优化,不会生成临时对象。

t2 = (Test)(40, 40);中是将(50,50)强转成Test类型,此时看似有两个40,其实只识别一个,判断是int类型,就去找Test有没有int类型的构造函数。
本质上和下一行改成t2 = 50;是一样的,是Test(50),所以调用构造函数,其中ma赋值为50,mb默认为20.

Test* p1 = new Test(70, 70);中,使用new的话,需要delete才能删除,不是临时变量,使用不会出语句后就析构

函数调用过程中对象背后调用的方法太多

实例代码:

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a = 10) :ma(a) { cout << "Test(int )" << endl; }
	~Test() { cout << "~Test()" << endl; }
	Test(const Test& src) :ma(src.ma) { cout << "Test(const Test&)" << endl; }
	void operator=(const Test& src)
	{
		cout << "operator=" << endl;
		ma = src.ma;
	}
	int getData()const
	{
		return ma;
	}

private:
	int ma;
};

Test getObject(Test t)
{
	int val = t.getData();
	Test tmp(val);
	return tmp;
}

int main()
{
	Test t1;
	Test t2;
	t2 = getObject(t2);

}

(注:不能返回局部的或临时对象的指针或引用)

结果:
在这里插入图片描述
第三句中
函数调用,实参=》形参 是初始化?还是赋值呢?
是初始化

在函数return tmp;时,直接给t2赋值?
错!
先在栈中创建一个临时对象(使用拷贝构造),然后先tmp析构

总结三条对象优化的规则.mp4

原则一: 函数参数传递过程中,对象优先按引用传递,不要按值传递。

可以省一个形参的构造和析构

Test getObject(Test &t)

原则二:函数返回对象的时候,应该优先返回一个临时对象,而不要返回定义过的对象

在用临时对象拷贝构造一个新对象时,如:

Test t = Test(30);

直接构造,不产生临时对象

Test getObject(Test &t)
{
	int val = t.getData();
	
	return Test(val);// 3 -- Test(int)
}

其次,我们虽然省去了在函数方法中创建临时对象,
即从:
函数方法中创建的对象=》main栈帧中创建临时对象用于传递=》传递给t2
变成了:
直接main栈帧中创建临时对象=》传递给t2
但是其实还可以优化
直接用构造方法构造t2
代码:

Test getObject(Test &t)
{
	int val = t.getData();
	
	return Test(val);// 3 -- Test(int)
}

int main()
{
	Test t1;// 1 -- Test(int)
	Test t2 = getObject(t2);

}

在这里插入图片描述

可以看出减少了很多构造和析构
**原则三:**接受返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收

添加带右值引用参数的拷贝构造和赋值函数

左值引用:有内存,有名字

int a = 10int &b = a;

右值引用:没名字(临时变量)或者没内存

int &c = 20;//没名字
int &&c = a; //无法将左值绑定到右值引用
int &&d = 20;//可以把一个右值绑定到右值引用上
int &&f = d;//右值引用,本身是这个左值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值