C++基础(一)构造函数、拷贝构造函数与赋值操作符

    对于C++初学者甚至是略有编程经验的研发人员来说,构造函数、拷贝构造函数、赋值操作符(赋值构造函数)既简单又难理解,甚至经常在这上面吃亏。网络上关于这三者的介绍也很多,其中不乏经典之作;但正是由于有关文章很多,良莠不齐,许多人的解释并不贴切,甚至是错误的,这导致许多初学者越看越糊涂。

    在很多文章中,将这三者放在一起讨论,甚至某些权威出版社的C++书籍也是如此,将赋值操作符叫做“赋值拷贝函数”,这是很不贴切的。赋值操作符(==)和构造函数根本没有半点关系。构造函数和拷贝构造函数,都是在有新的对象产生的时候编译器内部自动调用的,而赋值操作符,只是将一个已有对象的值赋值给另一个已有对象,并不会产生新的对象,只是在行为上,有些许像拷贝构造函数。所以,赋值操作符说是赋值拷贝函数,是非常不准确的一种说法!记住,赋值操作符只是一种操作符重载而已,和构造函数并有半点关系!

    构造函数其实很简单,就是创建具体对象的时候,编译器自动调用的类的特性函数,每个C++的类都会有。构造函数可以我们自己编写,如果我们没有自己编写,编译器会自动帮我们添加一个默认的构造函数。默认的构造函数不包含任何参数,对类里面的成员变量,也不会进行初始化。除了构造函数外,还有一个拷贝构造函数,如果我们没有手动编写编译器也会给我们自动增加一个。拷贝构造函数与构造函数的不同,是其包含一个类本身的const引用作为参数。例如编写了一个CTest类,其默认构造函数为CTest(),拷贝构造函数为CTest(const CTest& rTest)。需要注意的是,不管是构造函数还是拷贝构造函数,其成员变量的初始化,不应该放到函数体内,而是应该用成员初始化列表实现。(关于成员初始化列表,可自行查找,并不是本文的重点;另外,构造函数除了默认构造函数外,还可以带有各种参数,但是参数肯定不是其const引用,如果参数为其const引用,就是拷贝构造函数了;有关含有参数的构造函数,也需您自行查找资料)

    既然说构造函数和拷贝构造函数是编译器自动调用的,那么编译器什么时候会调用构造函数,什么时候会调用拷贝构造函数呢?我们只需要记住拷贝构造函数被调用的三种情况即可,除了这三种情况外,其他的任何有新对象创建的情形都是调用构造函数。拷贝构造函数调用的三种情况分别是:(1)当函数的形参是类的对象时(也就是值传递时);(2)当函数的返回值是类的对象;(3)用类的一个对象去初始化另一个对象时。具体的含义也需您自行查找(编程最主要的学习渠道就是自己去找资料弄清楚)。理解了这三点,就不难明白为什么拷贝构造函数里面的参数是引用了,因为如果不是引用而是类的对象,那么拷贝构造函数的形参还会调用拷贝构造函数,一直调用下去,就无限循环了。

    后面的代码是有关拷贝构造函数和构造函数的调用实例。

   

// "Constructor.h"
namespace ClassContructor
{
	class CBaseClass
	{
	public:
		CBaseClass();
		CBaseClass(const CBaseClass& cOther);
		CBaseClass& operator = (const CBaseClass& cOther);
		virtual ~CBaseClass();
	public: //此处为了测试方便,将成员变量声明为public,实际项目中,应该声明为private或者protected
		int m_nBaseTest; //用作测试的数	
		static int m_nConstructorCount; //构造函数调用次数
		static int m_nCopyCount; //拷贝构造函数调用次数
		static int m_nAssignCount; //赋值操作符调用次数
	};
	void TestClassConstructor();
}

//Constructor.cpp
#include <iostream>
#include <list>
namespace ClassContructor
{
	int CBaseClass::m_nConstructorCount = 0;
	int CBaseClass::m_nCopyCount = 0;
	int CBaseClass::m_nAssignCount = 0;
	CBaseClass::CBaseClass():m_nBaseTest(10) //构造函数设置m_nBaseTest为10
	{	
		++m_nConstructorCount; //构造函数次数+1
	}
	CBaseClass::CBaseClass(const CBaseClass& cOther):m_nBaseTest(cOther.m_nBaseTest + 1) //拷贝构造函数将m_nBaseTest值加1
	{
		++m_nCopyCount; //拷贝构造函数次数+1
	}
	CBaseClass& CBaseClass::operator = (const CBaseClass& cOther)
	{
		m_nBaseTest = cOther.m_nBaseTest;
		++m_nAssignCount; //赋值操作符次数+1
		return *this;
	}
	CBaseClass::~CBaseClass()
	{
	}
	void TestClassConstructor()
	{
		std::list<CBaseClass> lstDerived;
		for(int i = 0 ; i < 10; ++i)
		{
			/*先调用构造函数创建一个临时对象作为参数,push_back调用拷贝构造函数创建一个对象放到内存中,
			所以,lstDerived中对象的m_nBaseTest应该是11而不是10
			*/
			lstDerived.push_back(CBaseClass());  
		}
		std::cout << "constructor次数----------" << CBaseClass::m_nConstructorCount << std::endl;
		std::cout << "copy次数----------" << CBaseClass::m_nCopyCount << std::endl;
		std::cout << "=次数----------" << CBaseClass::m_nAssignCount << std::endl;
		std::cout << "m_nBaseTest = "  << lstDerived.back().m_nBaseTest << std::endl; 
	}
}

//main函数中调用
ClassContructor::TestClassConstructor();

main函数中调用后运行,结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值