/调用自定义的拷贝构造函数
static Test t4 = Test(30, 30);//t4起初开辟内存,在运行时调用拷贝构造函数
t2 = Test(40, 40);
//1.调用带有两个整型参(20,20)的构造函数构造临时对象 2.赋值运算符的重载函数 3.析构临时对象
t2 = (Test)(50, 50);//相当于强转逗号表达式,相当于t2=Test(50,5)[5是默认大小]
//1.调用带有两个整型参(20,20)的构造函数构造临时对象 2.赋值运算符的重载函数 3.析构临时对象
t2 = 60;//相当于隐式产生一个临时对象,等价于t2=Stack(60,5)
//1.调用带有两个整型参(20,20)的构造函数构造临时对象 2.赋值运算符的重载函数 3.析构临时对象
Test *p1 = new Test(70, 70);//动态开辟对象的内存,调用带有两个整型参的构造函数
Test *p2 = new Test[2];//动态开辟对象的内存,调用带有两个默认的构造函数
//堆上动态开辟的内存必须手动delete,否则永远不会析构
Test *p3 = &Test(80, 80);
//指针:1.调用带有两个整型参的构造函数构造一个临时对象 2.语句结束临时对象析构
Test &p4 = Test(90, 90);
//引用:调用带有两个整型参的构造函数构造一个临时对象,并给这个临时对象起了个别名p4,所以语句结束临时对象不会析构
delete p1;//手动释放p1所占用的外部资源
delete[]p2;//手动释放p2所占用的外部资源
}
Test t5(100, 100);//程序运行时开辟,调用带有两个整型参的构造函数
//释放的顺序是:p4,t3,t2,t4,t5,t1
运行结果为:
3.问题: C语言中空struct结构体的sizeof大小是0,而C++中空class类的sizeof大小是1个字节? struct结构体里只算变量的大小,存在变量,按照字节对齐原理计算字节大小,当结构为空时,就是没有变量存在,所以sizeof(struct)=0; 而在类class中,计算的是一个类的实例化对象所占空间的大小。每个实例在内存中都有独一无二的地址,为了达到这个目的,编译器往往会给空类隐含的加一个字节,这样空类在实例化后在内存中得到了独一无二的地址,所以空类所占的内存大小是1个字节。 /* 类的大小:
1.为类的非静态成员数据的类型大小之和;
2.由编译器额外加入的成员变量的大小,用来支持语言的某些特性(如:指向虚函数的指针);
3.为了优化存取效率,进行的边缘调整(字节对齐);
4.与类中的构造函数,析构函数以及其他的成员函数无关。
*/4.关于函数代码优化:
class Test
{
public:
Test(int a = 5) :ma(a)
{
cout << "Test(int=5)" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
Test(const Test &src) :ma(src.ma)
{
cout << "Test(const Test&)" << endl;
}
void operator=(const Test &src)
{
ma = src.ma;
cout << "operator=" << endl;
}
int getValue(){ return ma; }
private:
int ma;
};
第一种优化:
如果用值传递相当于产生了一个临时对象temp,Test a=temp;会调用拷贝构造函数,而在函数结束后还要析构临时对象,如果引用接收对象,就只是给本来的对象起了个别名,不会产生临时对象,更不用析构,提高代码效率。
优化一:函数参数传递过程中,要用引用接收对象,不要用值接受对象。
第二种优化:
如果返回已经存在的对象,还要在之前调用拷贝构造新函数先构造这个对象再返回它,函数结束之后再析构这个对象,如果直接返回临时对象,就不存在拷贝构造和析构的过程了,提高代码效率。
优化二:当函数返回一个对象时,要返回临时对象,不要返回已经存在的对象。
第三种优化:
以初始化的方式接收的话就直接调用构造函数构造t2,不会有临时对象的产生,此时代码效率达到最优。
优化三:以初始化的方式接收返回类型为对象的函数调用。