Day13(上).构造函数深究

关于有参构造函数 无参构造函数和copy构造函数的具体说明参见Day10:http://blog.csdn.net/jorg_zhao/article/details/46622449

有参构造函数的三种调用方法如下:

    //括号法  
    Test t1(10); //c++编译器自动调用这个类的有参构造函数  
    t1.print();  
  
    //=法  
    Test t2 = 20; //c++编译器自动调用这个类的有参构造函数  
    t2.print();  
  
    //手工调用初始化  
    Test t3 = Test(30);//程序员手工的调用构造函数 进行对象初始化  
    t3.print();  
copy构造函数有四种构造场景

1.拷贝构造函数的语法形式: 类名::类名(const 类名&引用名,...);

	Test(const Test &obj)
	{
		cout << "我是赋值构造函数" << endl;
	}

	Test t1;
	t1.SetBuf("我是T1");
	t1.SetAge(10);

	//赋值构造函数和=操作是两个不同的概念
	Test t2 = t1;
执行等号操作会跳转到拷贝构造函数,如果没有手动编写拷贝构造函数,编译器会默认提供一个拷贝构造函数。

2.用t1对象初始化t2对象

Test t2(t1);
3.函数的类类型实参初始化形参时,要调用拷贝构造函数

先看简单的两句代码

void func(Location p)
{
	cout << "Function:" << endl;
}
void main()
{
	Location A(1, 2);
	func(A);
	system("pause");
}
再给出完整的编译代码:

#include "iostream"
using namespace std;

class Location
{
private:
    int X, Y;
public:
    Location(int xx, int yy)
    {
        X = xx;
        Y = yy;
        cout << "构造函数调用" << endl;
    }
    Location(const Location &p)
    {
        X = p.X;
        Y = p.Y;
        cout << "拷贝构造函数调用" << endl;
    }
    ~Location()
    {
        cout << "析构函数调用:" << X << ',' << Y << endl;
    }

    int GetX()
    {
        return X;
    }
    int GetY()
    {
        return Y;
    }

};

void func(Location p)
{
    cout << "Function:" <<p.GetX()<<","<<p.GetY()<<endl;
}
void main22()
{
    Location A(1, 2);
    func(A);
}
void main()
{
    main22();
    system("pause");
}
需要注意的是:

1) 在实参传给形参的时候,会调用拷贝构造函数;

2)在析构时,首先是形参的析构,然后是实参的析构。


4.函数返回类类型时,通过拷贝构造函数建立临时对象。

Local func()
{
	Local A(1, 2);
	return A;
}
void main()
{
	Local B;
	B = func();
	system("pause");
}

1.构造函数

Local B;
2,

B = func();
Local A(1, 2);
A构造函数调用;

return A;
返回A的时候,由于A是局部变量,无法返回一个元素类,在C++中为了实现这种返回,会调用拷贝构造函数将其赋值给一个匿名对象,就像在内存中先创建一个匿名对象,再用A去初始化,并且A会析构,匿名对象不变。

3.

B = func();
当执行等号操作,将匿名对象赋值给B,匿名对象析构,最后B析构。

4.析构:A析构------匿名对象析构------B析构

最后给出完整的编译代码:

#include "iostream"
using namespace std;
/************************************************/

class Local
{
private:
	int X, Y;
public:
	Local(int xx = 0, int yy = 0)
	{
		X = xx;
		Y = yy;
		cout << "构造函数调用" << endl;
	}
	Local(const Local &p)
	{
		X = p.X;
		Y = p.Y;
		cout << "拷贝构造函数调用" << endl;
	}
	~Local()
	{
		cout << X << "," << Y << "析构函数调用" << endl;
	}

	int GetX(){ return  X; }
	int GetY(){ return Y; }
};
Local func()
{
	Local A(1, 2);
	return A;
}
void main33()
{
	Local B;
	B = func();
}

void main()
{
	main33();
	system("pause");
}

执行结果如下:

但是

如果是将上面的代码改成这样:

void main33()
{
	Local B = func();
}
这样执行的结果是什么呢???

结果是只执行两次构造和两次析构,为什么???????????????因为上面的代码是先执行等号右边的,等号右边执行以后返回一个匿名对象,恰巧等号左边有个B来接它,这时候C++编译器就优化的不会去执行B的构造函数,而是直接将匿名对象赋值给B,所以执行效率会比先构造再赋值的操作高!!!



浅拷贝和深拷贝的深入讲解:http://pan.baidu.com/s/1gdrkH9p

用内存的方式理解他俩的区别:假设每一个对象有两个参数,一个是指针,一个是大小。

  

                

从图中可以看出,如果使用深拷贝不当,会造成内存空间的扩大。


关于构造函数的规则:

1.当类中没有定义任何一个构造函数时,C++编译器会提供无参构造函数和拷贝构造函数;

2.当类中定义了任意的非拷贝构造函数(无参或有参),C++编译器会提供无参构造函数;

3.当类中定义了拷贝构造函数,C++编译器不会提供无参构造函数;

4.默认拷贝构造函数成员变量简单赋值;

结论:

如果你定义了拷贝构造函数,你必须要用!!!!!

继续深入:有参构造函数,初始化列表,看下面代码:

#include "iostream"
using namespace std;
/************************************************/
class A
{
private:
    int m_a;
public:
    A(int a)        //3,4. 调用A的构造函数
    {
        m_a = a;
        cout << m_a << endl;
    }
};

class B
{
private:
    int m_b;
    A a1;
    A a2;
public:
    B(int b) :a1(1), a2(2)    //2. B的构造函数构造前,会两次调用A的构造函数
    {
        m_b = b;    //5. 最后才是B的构造函数
        cout << m_b << endl;
    }
};

void main()
{
    B b(3);//1.这里会跳转到B的构造函数
    system("pause");
}


执行的顺序是上面标号:1,2,3,4,5











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值