🌈欢迎来到C++基础专栏
🙋🏾♀️作者介绍:前PLA队员 目前是一名普通本科大三的软件工程专业学生
🌏IP坐标:湖北武汉
🍉 目前技术栈:C/C++、Linux系统编程、计算机网络、数据结构、Mysql、Python(目前在学)
🍇 博客介绍:通过分享学习过程,加深知识点的掌握,也希望通过平台能认识更多同僚,如果觉得文章有帮助,请您动动发财手点点赞,本人水平有限,有不足之处欢迎大家扶正~
🍓 最后送大家一句话共勉:知不足而奋进,望远山而前行。
————————————————
析构函数、构造函数
- 1.构造函数
- 1.1说说构造函数有几种,分别有什么用
- 2.简述下向上转型和向下转型
- 3.简述下深拷贝和浅拷贝,如何实现深拷贝
1.构造函数
1.1说说构造函数有几种,分别有什么用
-
默认构造函数
给函数的参数提供默认初始化的值 -
初始化构造函数
给函数参数初始化 有初始化函数就不会使用默认构造函数
class Student
{
public:
//默认构造函数
Student()
{num=1001;age=18;
}
//初始化构造函数
Student(int n,int a):num(n),age(a){}
private:
int num;
int age;
};
int main()
{
//用默认构造函数初始化对象S1
Student s1;
//用初始化构造函数初始化对象S2
Student s2(1002,18);
return 0;
}
- 拷贝构造函数
复制一个类
class Test
{int i;int *p;
public:Test(int ai,int value){i = ai;p = new int(value);}~Test(){delete p;}Test(const Test& t){this->i = t.i;this->p = new int(*t.p);}
};
//复制构造函数用于复制本类的对象
int main(int argc, char* argv[])
{Test t1(1,2);Test t2(t1);//将对象t1复制给t2。注意复制和赋值的概念不同return 0;
}
- 移动构造函数
移动构造函数是C++11引入的一个特性,用于提高对象在内存中的移动效率,避免了不必要的深拷贝操作。移动构造函数通常用于实现右值引用(Rvalue Reference)的语义,其语法形式如下:
class MyClass {
public:// 移动构造函数MyClass(MyClass&& other) {// 执行移动操作,将资源从 other 转移到当前对象// 通常是通过将指针所有权转移,而不是进行深拷贝}// 其他成员函数和构造函数...
};
移动构造函数的关键是将资源(例如堆上分配的内存、文件句柄等)从一个对象“移动”到另一个对象,而不是进行拷贝。这可以大大提高性能,特别是在涉及大量数据或者资源时。
移动构造函数通常与右值引用一起使用,右值引用允许我们引用临时对象或者表达式的结果,从而在编译器级别上表示“这个对象即将被移动”。
MyClass createObject(); // 返回一个临时对象MyClass obj = createObject(); // 调用移动构造函数,而不是拷贝构造函数
在上述代码中,createObject() 返回一个临时对象,然后移动构造函数被调用来将这个临时对象的资源转移到 obj,而不是执行传统的拷贝操作。
移动构造函数的使用通常需要类具有管理资源的能力,例如使用动态分配的内存、文件句柄等。 C++ 标准库中的很多类都已经实现了移动构造函数,以提高性能。
2.简述下向上转型和向下转型
- 子类转换为父类:向上转型,使用dynamic_cast<type_id>(expression),这种转换相对来说比较
安全不会有数据的丢失; - 父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因
是父类的指针或者引用的内存中可能不包含子类的成员的内存。
3.简述下深拷贝和浅拷贝,如何实现深拷贝
浅拷贝:又称值拷贝,将源对象的值拷贝到目标对象中去,本质上来说源对象和目标对象共用一份
实体,只是所引用的变量名不同,地址其实还是相同的。举个简单的例子,你的小名叫西西,大名
叫冬冬,当别人叫你西西或者冬冬的时候你都会答应,这两个名字虽然不相同,但是都指的是你。
2. 深拷贝,拷贝的时候先开辟出和源对象大小一样的空间,然后将源对象里的内容拷贝到目标对象中
去,这样两个指针就指向了不同的内存位置。并且里面的内容是一样的,这样不但达到了我们想要
的目的,还不会出现问题,两个指针先后去调用析构函数,分别释放自己所指向的位置。即为每次
增加一个指针,便申请一块新的内存,并让这个指针指向新的内存,深拷贝情况下,不会出现重复
释放同一块内存的错误。
3. 深拷贝的实现:深拷贝的拷贝构造函数和赋值运算符的重载传统实现:
STRING( const STRING& s )
{//_str = s._str;_str = new char[strlen(s._str) + 1];strcpy_s( _str, strlen(s._str) + 1, s._str );
}
STRING& operator=(const STRING& s)
{if (this != &s){//this->_str = s._str;delete[] _str;this->_str = new char[strlen(s._str) + 1];strcpy_s(this->_str, strlen(s._str) + 1, s._str);}return *this;
}
这里的拷贝构造函数我们很容易理解,先开辟出和源对象一样大的内存区域,然后将需要拷贝的数
据复制到目标拷贝对象 , 那么这里的赋值运算符的重载是怎么样做的呢?
这种方法解决了我们的指针悬挂问题,通过不断的开空间让不同的指针指向不同的内存,以防止同一块内存被释放两次的问题。