首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >c++ 构造函数详解

c++ 构造函数详解

原创
作者头像
ruochen
修改2021-05-21 11:07:01
修改2021-05-21 11:07:01
7240
举报

c++ 构造函数详解

构造函数是干什么的

  • 该类对象被创建的时候,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员构造函数的分类 #include <iostream> using namespace std; class Coordinate { public: // 无参构造函数 // 如果创建一个类你没有写任何构造函数,则系统自动生成默认的构造函数,函数为空,什么都不干 // 如果自己显示定义了一个构造函数,则不会调用系统的构造函数 Coordinate() { c_x = 0; c_y = 0; } // 一般构造函数 Coordinate(double x, double y):c_x(x), c_y(y){} //列表初始化 // 一般构造函数可以有多个,创建对象时根据传入的参数不同调用不同的构造函数 Coordinate(const Coordinate& c) { // 复制对象c中的数据成员 c_x = c.c_x; c_y = c.c_y; } // 等号运算符重载 Coordinate& operator= (const Coordinate& rhs) { // 首先检测等号右边的是否就是等号左边的对象本身,如果是,直接返回即可 if(this == &rhs) return* this; // 复制等号右边的成员到左边的对象中 this->c_x = rhs.c_x; this->c_y = rhs.c_y; return* this; } double get_x() { return c_x; } double get_y() { return c_y; } private: double c_x; double c_y; }; int main() { // 调用无参构造函数,c1 = 0,c2 = 0 Coordinate c1, c2; // 调用一般构造函数,调用显示定义构造函数 Coordinate c3(1.0, 2.0); c1 = c3; //将c3的值赋值给c1,调用"="重载 Coordinate c5(c2); Coordinate c4 = c2; // 调用浅拷贝函数,参数为c2 cout<<"c1 = "<<"("<<c1.get_x()<<", "<<c1.get_y()<<")"<<endl <<"c2 = "<<"("<<c2.get_x()<<", "<<c2.get_y()<<")"<<endl <<"c3 = "<<"("<<c3.get_x()<<", "<<c3.get_y()<<")"<<endl <<"c4 = "<<"("<<c4.get_x()<<", "<<c4.get_y()<<")"<<endl <<"c5 = "<<"("<<c5.get_x()<<", "<<c5.get_y()<<")"<<endl; return 0; } c1 = (1, 2) c2 = (0, 0) c3 = (1, 2) c4 = (0, 0) c5 = (0, 0) 请按任意键继续. . .拷贝构造函数 #include <iostream> using namespace std; class Test { public: // 构造函数 Test(int a):t_a(a){ cout<<"creat: "<<t_a<<endl; } // 拷贝构造函数 Test(const Test& T) { t_a = T.t_a; cout<<"copy"<<endl; } // 析构函数 ~Test() { cout<<"delete: "<<t_a<<endl; } // 显示函数 void show() { cout<<t_a<<endl; } private: int t_a; }; // 全局函数,传入的是对象 void fun(Test C) { cout<<"test"<<endl; } int main() { Test t(1); // 函数中传入对象 fun(t); return 0; } creat: 1 copy test delete: 1 delete: 1 请按任意键继续. . .
  • 无参构造函数
  • 带默认值的构造函数
  • 有参(无默认值)的构造函数
  • 复制构造函数(拷贝构造函数) - 一种特殊的构造函数,当对象之间复制时会自动调用拷贝构造函数 - 若类中没有显示定义拷贝构造函数,则系统会自动生成默认拷贝构造函数
  • 拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类型的引用。当定义一个新对象并用同一类型的对象都它进行初始化时,将显示使用拷贝构造函数,当该类型的对象传递给函数返回该类型的对象时,将隐式调用拷贝构造函数
  • 当类中有一个数据成员是指针时,或者有成员表示在构造函数中分配的其他资源,必须显示定义拷贝构造函数
  • 构造函数的使用情况 - 一个对象以值传递的方式传入函数体 - 一个对象以值传递的方式从函数体返回 - 一个对象需要通过另一个对象进行初始化

浅拷贝与深拷贝

  • 浅拷贝 - 所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。也就是增加了一个指针,指向原来已经存在的内存。 正常情况下,“浅拷贝”已经能很好的工作,但是一旦对象存在动态成员,浅拷贝就会出问题。让我们考虑下面一段代码:
代码语言:txt
复制
	#include <iostream>
	#include <assert.h>    
	using namespace std;
	
	class Test
	{
	public:
		Test(){
			p = new int(10);
		}
	
		~Test(){
			assert(p != NULL);     // assert()作用是如果他的条件返回错误,则终止程序执行 
			delete p;
		}
	private:
		int x;
		int y;
		int* p;
	};
	
	int main()
	{
		Test t1;
		Test t2(t1);    // 调用默认拷贝构造函数
		return 0;
	}

上述程序崩溃。在使用t1复制t2时,进行的是浅拷贝,只是将成员的值进行赋值。此时,t1.p = t2.p, 即两个指针指向了堆里的同一个空间。这样,析构函数会被调用两次,这就是错误出现的原因。此问题的解决方法是“深拷贝”。

  • 深拷贝 - 深拷贝就是对于对象中的动态成员,并不只是简单的赋值,而是重新分配空间,即资源重新分配。上述代码处理如下: #include <iostream> #include <assert.h> using namespace std; class Test { public: Test(){ x = 0; y = 0; p = new int(10); } Test(const Test& t) { x = t.x; y = t.y; p = new int(10); *p = *(t.p); } ~Test(){ assert(p != NULL); // assert()作用是如果他的条件返回错误,则终止程序执行 delete p; } int get_x(){return x;} int get_y(){return y;} private: int x; int y; int* p; }; int main() { Test t1; Test t2(t1); // 调用默认拷贝构造函数 cout<<"("<<t1.get_x()<<", "<<t1.get_y()<<")"<<endl <<"("<<t2.get_x()<<", "<<t2.get_y()<<")"<<endl; return 0; }(0, 0) (0, 0) 请按任意键继续. . .此时t1与t2的p各自指向一段内存空间,但他们指向的内容相同,这就是“深拷贝”。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • c++ 构造函数详解
    • 构造函数是干什么的
    • 浅拷贝与深拷贝
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档