c++构造与析构

构造函数特性

名称与类名相同:构造函数的名称必须与类名完全相同,并且不能有返回值类型(包括void)。
自动调用:构造函数在对象实例化时自动调用,不需要手动调用。
初始化成员变量:构造函数的主要作用是初始化对象的成员变量。
重载:一个类可以有多个构造函数,只要它们的参数列表不同(即构造函数可以被重载)。
无返回值:构造函数不能有返回值类型。
初始化列表:构造函数可以使用初始化列表来初始化成员变量,特别是当成员变量是常量或引用类型时

#include <iostream>
using namespace std;class Point {
public:// 默认构造函数Point() {x = 0;y = 0;cout << "Default constructor called" << endl;}// 带参数的构造函数Point(int xVal, int yVal) {x = xVal;y = yVal;cout << "Parameterized constructor called" << endl;}void print() {cout << "Point(" << x << ", " << y << ")" << endl;}private:int x, y;
};int main() {Point p1; // 调用默认构造函数Point p2(10, 20); // 调用带参数的构造函数p1.print();p2.print();return 0;
}

继承中的调用顺序:在继承中,基类的构造函数会在派生类的构造函数之前被调用

默认构造函数: 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成

无参(默认)构造函数
有参构造函数
委托构造函数
复制(拷贝)构造函数
移动构造函数

有参,无参,拷贝三种构造函数对应三种调用方式示例

#include<iostream>
using namespace std;
class Person
{
public://默认构造函数Person();Person(){cout << "调用无参(默认)构造函数" << endl;}Person(int a){age = a;cout << "调用有参构造函数" << endl;}//拷贝构造函数用于拷贝传入的类到自身类上 //除了拷贝构造函数外都是普通构造函数Person(const Person &p)//传入的类不希望被改变所以加const 传入引用用p指向该类{age = p.age;cout << "调用拷贝构造函数" << endl;}~Person(){cout << "析构函数的调用" << endl;}int age;};
void test()
{//调用//1.括号法//注意:调用无参构造时不要输入()//Person p();会被编译器认为是函数的声明Person p;//调用无参构造函数Person p1(10);//调用有参函数构造Person p2(p1);//调用拷贝构造函数cout <<"p1的年龄"<< p1.age << endl;cout <<"p2的年龄"<< p2.age << endl;//2.显式法Person p3;//调用无参构造函数Person p4=Person (10);//调用有参函数构造Person p5=Person (p1);//调用拷贝构造函数//Person(10)为匿名对象 等号左侧就是它的名 //特点:当前行结束时,系统会立即回收掉匿名对象 即它的析构函数会在该行结束后就调用而不是test函数结束//3.隐式转换法Person p6 = 10; //调用有参函数构造 相当于Person p6=Person(10);  假如有两个参数就是 Person p6 = (10,9);Person p7 = p1;//调用拷贝构造函数 相当于Person p7=Person(p1);
}
int main()
{test();system("pause");return 0;
}#include<iostream>
using namespace std;
class Person
{
public://默认构造函数Person();//有参构造Person(int age, int height);int m_Age;int* m_Height;
};
//默认构造
Person::Person() 
{cout << "默认构造函数的调用!" << endl;this->m_Age = 0;this->m_Height = new int(0);
}
//有参构造,把age赋值给m_Age,身高用m_Height指向
Person::Person(int age,int height)
{cout << "有参构造函数的调用!" << endl;this->m_Age = age;this->m_Height = new int(height);
}
int main()
{Person p(18,175);cout << "此人的年龄是: " << p.m_Age << endl;cout << "此人的身高是: " << *(p.m_Height) << endl;return 0;
}

委托构造函数

委托构造函数就是把自己构造的事情,交给其他的构造函数顺带完成

#include<iostream>
using namespace std;
class Person
{
public://默认构造函数Person();//有参构造Person(int age, int height);//拷贝构造Person(const Person& p);int m_Age;int* m_Height;
};
//默认构造
Person::Person() :Person(0, 0)
{cout << "委托构造函数的调用!" << endl;
}
//有参构造,把age赋值给m_Age,身高用m_Height指向
Person::Person(int age, int height)
{cout << "有参构造函数的调用!" << endl;this->m_Age = age;this->m_Height = new int(height);
}
//拷贝构造函数调用
Person::Person(const Person& p)
{cout << "拷贝构造函数的调用!" << endl;this->m_Age = p.m_Age;this->m_Height = new int(*p.m_Height);
}
int main()
{Person p;cout << "p的年龄是: " << p.m_Age << endl;cout << "p的身高是: " << *(p.m_Height) << endl;return 0;
}
#include<iostream>
using namespace std;
class Person
{
public://默认构造函数Person();//有参构造Person(int age, int height);//拷贝构造Person(const Person& p);int m_Age;int* m_Height;
};
//默认构造
Person::Person()
{cout << "默认构造函数的调用!" << endl;this->m_Age = 0;this->m_Height = new int(0);
}
//有参构造,把age赋值给m_Age,身高用m_Height指向
Person::Person(int age, int height)
{cout << "有参构造函数的调用!" << endl;this->m_Age = age;this->m_Height = new int(height);
}
//拷贝构造函数调用
Person::Person(const Person& p)
{cout << "拷贝构造函数的调用!" << endl;this->m_Age = p.m_Age;this->m_Height = new int(*p.m_Height);
}
int main()
{Person p1(18, 175);cout << "p1的年龄是: " << p1.m_Age << endl;cout << "p1的身高是: " << *(p1.m_Height) << endl;Person p2(p1);//将对象p1复制给p2。注意复制和赋值的概念不同 cout << "p2的年龄是: " << p2.m_Age << endl;cout << "p2的身高是: " << *(p2.m_Height) << endl;return 0;
}
#include<iostream>
#include<string>
using namespace std;
class Point {
public:Point(int a,int b,int c){this->a = a;this->b = b;this->c = c;cout << "这是Pointd的有3个默认参数的构造函数!  "<<this->a<<" "<<this->b<<" "<<this->c<<endl;}Point(int a, int b){this-> a= a;this->b = b;Point(3, 4, 5);//产生一个匿名对象,纸条语句执行结束,匿名对象会被析构。cout << "这是Pointd的有2个默认参数的构造函数!  " << this->a << " " << this->b << endl;}~Point(){cout << "Point对象被析构了! "<<this->a << " " << this->b << " " << this->c << endl;}int getC(){return c;}
private:int a;int b;int c;};int run()
{Point aa(1, 2);cout << aa.getC() << endl;  //c的值为垃圾值,因为匿名对象被创建有立即析构了  
//就算用不析构的方式,也是垃圾值,因为c是不同对象中的元素     //在2个参数的构造函数中,没有显式初始化c,不能通过构造其他对象而在本构造对象中访问未初始化的数据return 0;
}
int main()
{run();cout << "hello world!\n";return 0;
}

C++之构造函数的初始化参数表

初始化列表是成员变量定义的地方
不管有没有显示写初始化参数列表,编译器在调用构造函数时都会先走初始化参数列表
在C++11新特性中,允许在类中声明变量时给上缺省值,这里的缺省值实际上是给初始化参数列表使用的
初始化参数列表初始化的顺序与成员函数的声明顺序一致

class A{
public://在函数的括号后使用 : 成员变量(参数) 使用逗号进行分割//A(int a,int b):x(a),y(b){}A(int a,int b): x(a), y(b){}
private:int x;int y;
};
struct Test1
{Test1() // 无参构造函数{ cout << "Construct Test1" << endl ;}Test1(const Test1& t1) // 拷贝构造函数{cout << "Copy constructor for Test1" << endl ;this->a = t1.a ;}Test1& operator = (const Test1& t1) // 赋值运算符{cout << "assignment for Test1" << endl ;this->a = t1.a ;return *this;}int a ;
};struct Test2
{Test1 test1 ;Test2(Test1 &t1){test1 = t1 ;}
};

常用构造:
Test1() // 无参构造函数
A(int a,int b):x(a),y(b){}//构造函数初始化参数表
Test1(const Test1& t1) // 拷贝构造函数
Test1& operator = (const Test1& t1) // 赋值运算符

初始化列表实例

class Stack {
public:Stack(int capacity = 10): _a((int*)malloc(sizeof(int))), _top(0), _capacity(capacity){if (nullptr == _a){perror("fail malloc");exit(-1);}memset(_a, 0, sizeof(int) * capacity);}
private:int* _a;int _top;int _capacity;
};
class A {
public:A():_x(1),_a1(3),_a2(1),_z(_a1){_a1++;_a2--;}
private:int _a1 = 1;	//声明int _a2 = 2;const int _x;int& _z;B _bb;
};

析构函数

清理资源:析构函数通常用于释放对象在其生命周期内分配的资源,例如动态分配的内存、打开的文件句柄等

#include <iostream>
using namespace std;class Example {
public:// 构造函数Example() {cout << "Constructor called" << endl;data = new int[10]; // 动态分配内存}// 析构函数~Example() {cout << "Destructor called" << endl;delete[] data; // 释放动态分配的内存}private:int* data;
};int main() {Example ex; // 创建对象,调用构造函数// 对象生命周期结束时,自动调用析构函数return 0;
}#include <iostream>
using namespace std;
//构造函数的实现
class Student
{
public:     //:flag(Flag)解释:类内变量(参数)Student(int Flag,char Sex, string Name, const char *File); //类外参数列表函数声明//类内使用方式,不需要声明// Student(int Flag,char Sex, string Name) :flag(Flag),sex(Sex),name(Name) //构造函数// {//   // //错误形式://   // int a=10;//   // int &b;//   // b=a; //大错特错//   cout<<"类内:flag="<<this->flag<<endl;//   cout<<"类内:sex="<<this->sex<<endl;//   cout<<"类内:name="<<this->name<<endl;// }private:int &flag;  //必须用参数列表方式char sex;string name;const char *file = NULL;  //必须使用参数列表方式//引用变量定义法则->构造函数名(参数):引用变量名(参数)};//类外构造函数
Student::Student(int Flag,char Sex, string Name,const char *File):flag(Flag),sex(Sex),name(Name),file(File) //构造函数{// //错误形式:// this->flag=Flag;相当于以下:// int a=10;// int &b;// b=a; //大错特错cout<<"类内:flag="<<this->flag<<endl;cout<<"类内:sex="<<this->sex<<endl;cout<<"类内:name="<<this->name<<endl;cout<<"类内:file="<<this->file<<endl;}
int main(int argc, char const *argv[])
{Student st(100,'M',"JKJK","/usr/include/linux/fb.h");  //先创建了对象,后执行构造函数return 0;
}struct foo
{int i ;int j ;foo(int x):i(x), j(i){}; // ok, 先初始化i,后初始化j
};

浅拷贝

int* shallowCopy(int* original) {return original; // 只是复制了指针,没有复制指针指向的内存
}

浅拷贝只是复制了对象的引用或指针,而不是复制对象所指向的资源

深拷贝

int* deepCopy(int* original, size_t size) {int* copy = new int[size];std::copy(original, original + size, copy);return copy; // 复制了指针指向的内存
}
class MyArray {
public:MyArray(size_t size) : size_(size), data_(new int[size]) {}~MyArray() { delete[] data_; }// 禁用拷贝构造函数和赋值操作符以防止浅拷贝MyArray(const MyArray&) = delete;MyArray& operator=(const MyArray&) = delete;// 实现深拷贝的拷贝构造函数MyArray(const MyArray& other) : size_(other.size_), data_(new int[other.size_]) {std::copy(other.data_, other.data_ + size_, data_);}// 实现深拷贝的赋值操作符MyArray& operator=(MyArray other) {std::swap(size_, other.size_);std::swap(data_, other.data_);return *this;}
​
private:size_t size_;int* data_;
};

有时间继续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/10675.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构之带头双向循环链表

前言&#xff1a;前面我们实现了顺序表和单链表&#xff0c;这次来实现一个结构更复杂的链表-----带头双向循环链表。不要被它的名字吓到哦&#xff0c;只是结构复杂而已&#xff0c;它的结构更有利于代码的实现。 1 双向循环链表的介绍 有了单链表的基础&#xff0c;要实现这…

10个最常用的Python包,程序员必备!

世界上有超过200,000个Python程序包&#xff08;这只是基于官方的Python程序包索引PyPI托管的程序包&#xff09;。 这就引出了一个问题&#xff1a;拥有这么多的软件包&#xff0c;每个Python程序员都需要学习哪些软件包是最重要的&#xff1f; 为了帮助回答这个问题&#x…

线上问题的排查-java死锁问题如何排查

这里写目录标题 1.java死锁如何排查2.具体步骤1.1识别死锁现象1.2收集线程转储1.3分析线程转储1.4代码审查1.5重现问题1.6使用调试工具1.7.优化和验证 3. 解决方案总结 1.java死锁如何排查 在Java应用程序中&#xff0c;死锁是一个经典的并发问题&#xff0c;它会导致线程永久阻…

shodan(4-5)

以下笔记学习来自B站泷羽Sec&#xff1a; B站泷羽Sec 1. 查看自己的出口IP 可以知晓自己是哪个IP连接的公网 shodan myip2. 指定标题搜索 http.title:内容搜索被挂黑页的网页&#xff1a;获得标题中含有hacked by的IP shodan search --limit 10 --fields ip_str,port htt…

三种风格截然不同的实验室工控界面

三种风格截然不同的实验室工控界面各具特色。一种可能是简洁现代风&#xff0c;以简洁的线条、纯净的色彩和直观的图标&#xff0c;呈现出高效与专业。 另一种或许是科技未来风&#xff0c;运用炫酷的光影效果和立体感十足的设计&#xff0c;展现实验室的前沿科技感。 还有一…

Redis如何保证数据不丢失(可靠性)

本文主要以学习为主&#xff0c;详细参考&#xff1a;微信公众平台 Redis 保证数据不丢失的主要手段有两个&#xff1a; 持久化 多机部署 我们分别来看它们两的具体实现细节。 1.Redis 持久化 持久化是指将数据从内存中存储到持久化存储介质中&#xff08;如硬盘&#xf…

STM32F405RGT6单片机原理图、PCB免费分享

大学时机创比赛时画的板子&#xff0c;比到一半因为疫情回家&#xff0c;无后续&#xff0c;&#xff0c;&#xff0c;已打板验证过&#xff0c;使用stm32f405rgt6做主控 下载文件资源如下 原理图文件 pcb文件 外壳模型文件 stm32f405例程 功能 以下功能全部验证通过 4路…

“穿梭于容器之间:C++ STL迭代器的艺术之旅”

引言&#xff1a; 迭代器&#xff08;Iterator&#xff09;是C STL&#xff08;标准模板库&#xff09;中非常重要的一部分&#xff0c;它提供了一种统一的方式来遍历容器中的元素。无论容器是数组、链表、树还是其他数据结构&#xff0c;迭代器都能够以一致的方式访问这些数据…

jmeter常用配置元件介绍总结之用linux服务器压测

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之用linux服务器压测 1.编写测试脚本2.执行测试脚本 1.编写测试脚本 在linux服务器上进行压测&#xff0c;由于是没有界面的&#xff0c;因此我们可以先在界面上把压测脚本写好&#xff1a; 如图&#xff1a;我这里简单的写…

Ubuntu 的 ROS 操作系统安装与测试

引言 机器人操作系统&#xff08;ROS, Robot Operating System&#xff09;是一个用于开发机器人应用的开源框架&#xff0c;它提供了一系列功能丰富的库和工具&#xff0c;能够帮助开发者构建和控制机器人。 当前&#xff0c;ROS1的最新版本为Noetic Ninjemys&#xff0c;专为…

计算机组成原理——编码与纠错(汉明编码)

校验码放在2^x次方的位置——即1&#xff0c;2&#xff0c;4——将检测位按序排列p3p2p1 汉明编码从左到右数某个位置位1&#xff08;位数&#xff09;&#xff0c;就表示第几组 奇偶校验 例题 纠错过程 汉明编码的最小距离是3

fabric操作canvas绘图(1)共32节

对于前端而言&#xff0c;离不开canvas就像鱼离不开水&#xff0c;前端canvas神器fabric你值得拥有&#xff01;接下来我们就来一步步揭开她的面纱。 一、fabric的理解 用原生的canvas来实现&#xff0c;代码量会比较大&#xff0c;而且还要处理很多细节&#xff0c;而Fabric…

C++ 内存分布及 new , delete 分配问题( ~~~ 面试重要 ~~~)

文章目录 前言一、内存分布二、new 、delete 分配问题总结 前言 本篇文章笔者将会对 C 中的内存问题简单的讲解 , 同时对 new , delete 的面试题进行重点讲解. 一、内存分布 ● C语言和C 分布情况是一样的, 如下 : ● 栈 ○ 栈 的管理是由编译器自动管理 , 不需要我们人为做…

数据结构-哈夫曼树

一.什么是哈夫曼树 不同搜索树的效率是不一样的,根据不同的频率构造效率比较好或者最好的搜索树就是哈夫曼树 二.哈夫曼树的定义 将带权路径的长度降低最低 每个叶子节点到根节点的距离乘权值&#xff0c;再全都加起来就得到了WPL值 第一颗二叉树:从上到下计算 5x14x23x32x41…

双11精选网络安全书单:打造数字世界的钢铁长城!

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 &#x1f31f;双11火热来袭&#xff0c;网络安全书单推荐&#x1f680; 随着数字化浪潮的汹涌澎湃&#xff0c;网络安全已经成为了每个从业者不可回避的重要议…

WebGUI之Gradio:Gradio 5的简介、安装和使用方法、案例应用之详细攻略

WebGUI之Gradio&#xff1a;Gradio 5的简介、安装和使用方法、案例应用之详细攻略 目录 Gradio 5的简介 1、Gradio的适用场景 2、Gradio 5 的主要改进包括&#xff1a; Gradio 5的安装和使用方法 1、安装和使用方法 2、使用方法 2.1、文本内容 (1)、简单的输入/输出组件…

初始Python篇(5)—— 集合

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 集合 相关概念 集合的创建与删除 集合的操作符 集合的相关操作方法 集合的遍历 集合生成式 列表、元组、字典、集合的…

探索Python的Shell力量:Plumbum库揭秘

文章目录 探索Python的Shell力量&#xff1a;Plumbum库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;Plumbum是什么&#xff1f;第三部分&#xff1a;如何安装Plumbum&#xff1f;2. 创建管道3. 重定向4. 工作目录操作5. 前台和后台执行 第五部分&#xff1a;场景应用…

大模型时代,算法岗到底哪个最有前景?什么样的算法工程师更吃香?

毫无疑问&#xff0c;全栈型的算法工程师将更为抢手&#xff0c;如果你精通大模型从训练到应用的整个流程&#xff0c;你走到哪里都不怕。 但往往人的精力有限&#xff0c;如果从数据、预训练、微调、对齐、推理、应用几个方面来看的话&#xff0c;个人觉得 “预训练>数据&…

Linux系统之sleep命令的基本使用

Linux系统之sleep命令的基本使用 一、sleep命令介绍二、sleep的使用帮助2.1 查看帮助信息2.2 基本语法 三、sleep命令的基本使用3.1 指定暂停时间长度3.2 结合多个时间单位 四、在脚本中应用五、注意事项 一、sleep命令介绍 sleep命令是一个在Unix和类Unix操作系统中常见的命令…