【C++】C++11--- 类的新功能

目录

类的新功能

默认成员函数

示例

类成员变量初始化

强制生成默认函数的关键字default

禁止生成默认函数的关键字delete


类的新功能

默认成员函数

  • 构造函数
  • 析构函数
  • 拷贝构造函数
  • 拷贝赋值重载
  • 取地址重载
  • const取地址重载

C++11在原先的6个默认成员函数的基础上,新增了2个:【移动构造函数】和【移动赋值运算符重载


默认移动构造的生成条件

条件1:开发者不显示实现移动构造函数;

条件2:析构函数、拷贝构造、赋值运算符重载函数任意一个都没有显示实现;

当同时满足条件1与条件2,编译器自动生成移动构造函数;

移动构造函数的规则

  • 移动构造函数对于内置类型成员按字节序完成值拷贝;
  • 移动构造函数对于自定义类型成员调用自定义类型的移动构造,若自定义类型成员没有移动构造,便调用其拷贝构造;

默认移动赋值的生成条件

条件1:开发者不显示实现移动赋值函数;

条件2:析构函数、拷贝构造、赋值运算符重载函数任意一个都没有显示实现;

当同时满足条件1与条件2,编译器自动生成移动赋值函数;

移动赋值函数的规则

  • 移动赋值函数对于内置类型成员直接赋值;
  • 移动赋值函数对于自定义类型成员调用自定义类型的移动赋值,若自定义类型成员没有移动赋值,便调用其赋值运算符重载函数;

开发者显示提供移动构造与移动赋值,编译器不再自动生成移动构造与移动赋值;

示例

namespace RightReference
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){//cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}// 拷贝构造string(const string& s):_str(nullptr){cout << "string(const string& s) --- 深拷贝" << endl;_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}//移动构造--右值string(string&& s){cout << "string(string&& s) -- 移动拷贝" << endl;swap(s);}// 拷贝赋值string& operator=(const string& s){cout << "string& operator=(const string& s) --- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}// 移动赋值--右值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 移动拷贝" << endl;swap(s);return *this;}~string(){delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}string& operator+=(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;};
}class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}/*Person(const Person& p):_name(p._name),_age(p._age){}*//*Person& operator=(const Person& p){if(this != &p){_name = p._name;_age = p._age;}return *this;}*//*~Person(){}*/private:RightReference::string _name;int _age;
};int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);Person s4;s4 = std::move(s2);return 0;
}

类成员变量初始化

默认生成的构造函数,对于自定义类型的成员会调用其构造函数进行初始化,但并不会对内置类型的成员进行处理;于是C++11支持非静态成员变量在声明时进行初始化赋值,默认生成的构造函数会使用这些缺省值对成员进行初始化;比如:

class Person
{
public://...
private://非静态成员变量,可以在成员声明时给缺省值RightReference::string _name = "peter";int _age = 20;static int _n; //静态成员变量不能给缺省值
};

强制生成默认函数的关键字default

C++11可以更好的控制要使用的默认成员函数,假设在某些情况下需要使用某个默认成员函数,但是因为某些原因导致无法生成这个默认成员函数,这时可以使用default关键字强制生成某个默认成员函数;

例如:我们提供了拷贝构造函数,就不会生成默认移动构造了,那么我们可以使用default关键字强制生成移动构造;

class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p):_name(p._name),_age(p._age){}//强制生成移动构造Person(Person&& p) = default;
private:RightReference::string _name;int _age;
};int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);return 0;
}

例如:Person类中只实现了拷贝构造函数,没有实现构造函数,由于拷贝构造函数本身也是构造函数,默认构造不再自动生成;

class Person
{
public://拷贝构造函数Person(const Person& p):_name(p._name),_age(p._age){}private:RightReference::string _name;int _age;
};int main()
{Person s1;//error 没有合适的默认构造函数使用return 0;
}

此时可以使用default关键字强制生成默认的构造函数,如下:

class Person
{
public:Person() = default;//拷贝构造函数Person(const Person& p):_name(p._name),_age(p._age){}private:RightReference::string _name;int _age;
};int main()
{Person s1;//error 没有合适的默认构造函数使用return 0;
}

禁止生成默认函数的关键字delete

C++98中,不期望某个类的对象被拷贝,得限制默认的拷贝构造函数的生成,一般的处理方式为将拷贝构造函数只声明不实现并且将此声明置于私有,如此外部调用时便会报错;

class Person
{
public:Person(const char* name=" ",int age=0):_name(name),_age(age){}
private://拷贝构造函数Person(const Person& p);RightReference::string _name;int _age;
};int main()
{Person s1("Linda", 20);Person s2 = s1;//errorreturn 0;
}

C++中只需要在拷贝构造函数的声明中加上=delete即可,该语法指示编译器不再生成拷贝构造函数的默认版本,称=delete修饰的函数为删除函数

class Person
{
public:Person(const char* name=" ",int age=0):_name(name),_age(age){}//拷贝构造函数Person(const Person& p) = delete;private:RightReference::string _name;int _age;
};int main()
{Person s1("Linda", 20);Person s2 = s1;//error 尝试引用已删除的函数return 0;
}

欢迎大家批评指正,博主会持续输出优质内容,谢谢各位观众老爷观看,码字画图不易,希望大家给个一键三连支持~ 你的支持是我创作的不竭动力~

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebDriver使用带用户名密码验证的IP代理解决方案

背景&#xff0c;使用python3 selenium 先定义一个方法&#xff0c;这里主要用到了chrome插件的功能&#xff0c;利用这个插件来放进代理内容。 def create_proxy_auth_extension(proxy_host, proxy_port,proxy_username, proxy_password, schemehttp):manifest_json "…

【Java基础】Maven继承

1. 前言 Maven 在设计时&#xff0c;借鉴了 Java 面向对象中的继承思想&#xff0c;提出了 POM 继承思想。 2. Maven继承 当一个项目包含多个模块时&#xff0c;可以在该项目中再创建一个父模块&#xff0c;并在其 POM 中声明依赖&#xff0c;其他模块的 POM 可通过继承父模…

基于TF的简易关键字语音识别

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计10182字&#xff0c;阅读大概需要10分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#…

word文件名和创建时间可以同时提取出来吗?答案是肯定的!方法很简单 一键就搞定

在日常生活和工作中&#xff0c;我们经常需要处理大量的Word文件&#xff0c;有时候需要提取这些文件的文件名以及它们的创建时间。虽然这听起来可能是一个复杂的任务&#xff0c;但实际上&#xff0c;通过一些简单的方法和工具&#xff0c;我们可以轻松地完成这一任务。在本文…

「C++ 内存管理篇 04」动态二维数组

目录 一. 使用calloc/free开辟和释放二维数组 二、 使用new/delete开辟和释放二维数组 一. 使用calloc/free开辟和释放二维数组 让一个二级指针变量存放动态开辟的一级指针数组的起始地址&#xff0c;然后让这些一级指针指向动态开辟的基本类型的数组&#xff1a; // 开辟一个大…

机器学习项目实践-基础知识部分

环境建立 我们做项目第一步就是单独创建一个python环境&#xff0c;Python新的隔离环境 创建&#xff1a;python -m venv ml 使用&#xff1a;.\Scripts\activate python -m venv ml 是在创建一个名为 ml 的虚拟环境&#xff0c;这样系统会自动创建一个文件夹ml&#xff0c;…

YOLOv5改进(一)MobileNetv3替换主干网络

前言 本篇博客主要讲解YOLOv5主干网络的替换&#xff0c;使用MobileNetv3实现模型轻量化&#xff0c;平衡速度和精度。以下为改进的具体流程~ 目录 一、改进MobileNetV3_Small 第一步&#xff1a;修改common.py,新增MobileNetV3 第二步&#xff1a;在yolo.py的parse_model函…

算法提高之玉米田

算法提高之玉米田 核心思想&#xff1a;状态压缩dp 将图存入g数组 存的时候01交换一下方便后面判断即g数组中0为可以放的地方 state中1为放的地方 这样只要state为1 g为0就可以判断不合法 #include <iostream>#include <cstring>#include <algorithm>#includ…

linux 内核编译

目录 Linux操作系统框架 Linux内核的主要功能&#xff1a; Linux的内核目录结构&#xff1a; 结构图: 详细介绍&#xff1a; uname - a 补充 编译之前 UTC 时间补充 Linux内核编译流程: 方法一: 官方内核编译: 1. 运行 build.sh 脚本&#xff0c; 记得加 sudo 权…

【RAG 论文】GenRead:“generate-read“ 可能比 “retrieve-read“ 更有效

论文&#xff1a;Generate rather than Retrieve: Large Language Models are Strong Context Generators ⭐⭐⭐⭐ ICLR 2023 Code: github.com/wyu97/GenRead 一、论文速读 该工作发现&#xff1a;由 LLM 生成的文档中&#xff0c;往往比 retrieved documents 更可能包含正确…

mysql5.7数据库安装及性能测试

mysql5.7数据库安装及性能测试 记录Centos7.9下安装mysql 5.7并利用benchmark工具简单测试mysql的性能。 测试机&#xff1a;centos7.9 配置&#xff1a;4C8G40G 1. 下安装mysql5.7 安装mysql5.7&#xff1a; # 通过官方镜像源安装$ wget http://dev.mysql.com/get/mysql57-com…

医药垃圾分类管理系统|基于SSM医药垃圾分类管理系统的系统设计与实现(源码+数据库+文档)

医药垃圾分类管理系统 目录 基于SSM医药垃圾分类管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统登录模块 2管理员模块实现 3用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博…