c++(强生成关键字+可变参数模板+emplace)[26]

news2025/1/11 22:57:55

强制生成 不生成

在C++中,可以通过一些方式来控制编译器是否生成某些特殊成员函数(如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等)。

  1. 默认生成:如果你没有显式地定义这些特殊成员函数,编译器会自动生成它们。这被称为默认生成。默认生成的成员函数会根据类的特性进行生成,例如默认构造函数会生成一个无参构造函数,拷贝构造函数会生成一个按值拷贝的构造函数。

  2. 强制生成:如果你显式地声明了某个特殊成员函数,但是不提供其定义,编译器将不会生成该函数的默认实现。这被称为强制生成。通过强制生成,你可以禁止某些特殊成员函数的自动生成,从而实现特定的语义或行为。

  3. 不生成:如果你显式地删除了某个特殊成员函数,编译器将不会生成该函数的默认实现。这被称为不生成。通过不生成,你可以禁止某些特殊成员函数的使用,从而防止不希望的行为或错误。

下面是一些示例代码,展示了如何强制生成或不生成特殊成员函数:

class MyClass {
public:
    // 强制生成默认构造函数
    MyClass() = default;

    // 强制生成拷贝构造函数
    MyClass(const MyClass& other) = default;

    // 不生成拷贝赋值运算符
    MyClass& operator=(const MyClass& other) = delete;

    // 强制生成析构函数
    ~MyClass() = default;
};

在上面的示例中,我们通过使用default关键字来强制生成默认构造函数、拷贝构造函数和析构函数。同时,我们通过使用delete关键字来不生成拷贝赋值运算符。

需要注意的是,强制生成或不生成特殊成员函数是一种高级用法,需要谨慎使用。你应该根据具体的需求和设计来决定是否需要强制生成或不生成某些特殊成员函数。

// 以下代码在vs2013中不能体现,在vs2019下才能演示体现上面的特性。
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(Person&& p) = default;
	Person& operator=(Person&& p) = default;
	//不想生产(让Person对象拷贝)
	Person(const Person& p) = delete;
	
		~Person()
		{
			cout << "~Person()" << endl;
		}
	
	private:
		bit::string _name; // 自定义类型
		int _age = 1;		   // 内置类型
	};
	
	int main()
	{
		Person s1("张三", 18);
		Person s2 = s1;
		Person s3 = std::move(s1);
		cout << endl << endl;
		Person s4;
		s4 = std::move(s2);
	
		return 0;
	}

final || override

在C++中,finaloverride是两个关键字,用于对类的成员函数进行修饰和控制。

  1. final关键字:final用于修饰类、虚函数和成员函数,表示它们不能被继承、重写或覆盖。当一个类被声明为final时,其他类就不能从该类派生。当一个虚函数被声明为final时,它不能在派生类中被重写或覆盖。当一个非虚函数被声明为final时,它不能在派生类中被重新定义。
class Base final {
    // ...
};

class Derived : public Base {  // 错误,Base类被声明为final,不能被继承
    // ...
};

class Base {
public:
    virtual void foo() final {
        // ...
    }
};

class Derived : public Base {
public:
    void foo() override {  // 错误,foo函数被声明为final,不能被重写
        // ...
    }
};
  1. override关键字:override用于修饰派生类中的虚函数,表示该函数是对基类中的虚函数的重写。使用override可以提高代码的可读性和安全性,确保派生类中的函数与基类中的虚函数具有相同的签名。
class Base {
public:
    virtual void foo() {
        // ...
    }
};

class Derived : public Base {
public:
    void foo() override {  // 明确标记为重写虚函数
        // ...
    }
};

如果在派生类中使用了override关键字修饰一个函数,但该函数并不是基类中的虚函数,编译器将会报错。

总之,finaloverride是C++11引入的关键字,用于对类的成员函数进行修饰和控制。final表示类或函数不能被继承、重写或覆盖,而override表示派生类中的函数是对基类中虚函数的重写。

要求delete关键字实现,一个类,只能在堆上创建对象

当构造函数被声明为私有时,它只能在类的内部被访问。这意味着在类的外部无法直接调用构造函数来创建对象。因此,将构造函数设为私有可以阻止类在栈上创建对象的方式。

在C++中,当你在栈上声明一个对象时,编译器会在编译时自动调用类的构造函数来创建对象。但是,如果构造函数是私有的,编译器将无法调用该构造函数,从而阻止了在栈上创建对象的方式。

以下是一个示例代码,展示了私有构造函数如何阻止类在栈上创建对象的方式:

class MyClass {
private:
    MyClass() {}  // 私有的构造函数

public:
    void doSomething() {
        // 对象的成员函数
    }
};

int main() {
    MyClass obj;  // 编译错误!无法调用私有构造函数

    return 0;
}

在上面的示例中,我们将构造函数声明为私有的,然后在main()函数中尝试在栈上创建一个MyClass对象。由于构造函数是私有的,编译器将无法调用该构造函数,从而导致编译错误。

需要注意的是,尽管无法在栈上直接创建对象,但仍然可以通过其他方式(如静态成员函数或友元函数)在堆上创建对象。

class HeapOnly
{
public:
	~HeapOnly() = delete;
};
int main()
{
	//HeapOnly hp1;
	//static HeapOnly hp2;          //自定义类型会调用析构

	HeapOnly* ptr = new HeapOnly;  //指针不会调用析构

	return 0;
}

下面例子此时会有资源泄露

class HeapOnly
{
public:
	HeapOnly()
	{
		_str = new char[10];
	}
	~HeapOnly() = delete;
private:
	char* _str;
};
int main()
{
	//HeapOnly hp1;
	//static HeapOnly hp2;          //自定义类型会调用析构

	HeapOnly* ptr = new HeapOnly;  //指针不会调用析构
	//delete ptr;                  //无析构 不能delete
	return 0;
}

自写destroy解决

// 要求delete关键字实现,一个类,只能在堆上创建对象
class HeapOnly
{
public:
	HeapOnly()
	{
		_str = new char[10];
	}
	~HeapOnly() = delete;
	void Destroy()
	{
		delete[] _str; 
		operator delete(this);
	}
private:
	char* _str;
};
int main()
{
	//HeapOnly hp1;
	//static HeapOnly hp2;          //自定义类型会调用析构

	HeapOnly* ptr = new HeapOnly;  //指针不会调用析构
	//delete ptr;                  //无析构 不能delete
	ptr->Destroy();

	return 0;
}

可变参数模板

在这里插入图片描述

//可变参数的函数模板
template <class ...Args>
void ShowList(Args... args)
{
	cout<< sizeof...(args) <<endl;  //计算几个参数
}
int main()
{
	string str("hello");
	ShowList(1);
	ShowList();
	ShowList(1, 2);
	ShowList(1, 'A', str);

	return 0;
}

在这里插入图片描述
递归看参数

//可变参数的函数模板
void ShowList()
{
	cout << endl;
}

template <class T, class ...Args>
void ShowList(const T& val, Args... args)
{
	cout << val << " ";
	ShowList(args...);
	//cout<< sizeof...(args) <<endl;
}
int main()
{
	string str("hello");
	ShowList(1);
	ShowList();
	ShowList(1, 2);
	ShowList(1, 'A', str);

	return 0;
}

结果

1

1 2
1 A hello

列表初始化获取

template<class T>
int PrintArg(const T& x)
{
	cout << x << " ";
	return 0; 
}
template <class ...Args>
void ShowList(Args... args)
{
	int a[] = { PrintArg(args)... };
	cout << endl;
}
int main()
{
	string str("hello");
	ShowList(1);
	ShowList();
	ShowList(1, 2);
	ShowList(1, 'A', str);

	return 0;
}

emplace

emplace_back()是C++标准库容器(如vector、list和deque)提供的一个成员函数,用于在容器的末尾直接构造对象,而不需要显式地调用构造函数。

emplace_back()的优势主要体现在以下几个方面:

  1. 减少对象的拷贝或移动:使用emplace_back()可以直接在容器的末尾构造对象,而不需要先创建一个临时对象,然后再将其拷贝或移动到容器中。这样可以减少不必要的对象拷贝或移动操作,提高代码效率。

  2. 简化代码:相比于显式地调用构造函数和push_back()函数,使用emplace_back()可以更简洁地创建对象并将其添加到容器中。你只需要传递构造函数所需的参数,而不需要创建临时对象或手动调用构造函数。

  3. 支持完美转发:emplace_back()函数支持完美转发,可以将参数直接传递给构造函数,无需手动进行类型转换。这意味着你可以使用不同类型的参数来构造对象,而不需要为每个类型编写重载的构造函数。

以下是一个使用emplace_back()的示例代码:

#include <vector>

class MyClass {
public:
    MyClass(int x, int y) {
        // 构造函数的实现
    }
};

int main() {
    std::vector<MyClass> myVector;
    myVector.emplace_back(10, 20);  // 在容器的末尾构造对象

    return 0;
}

在上面的示例中,我们使用emplace_back()函数在myVector容器的末尾直接构造了一个MyClass对象,而不需要先创建一个临时对象。

总而言之,emplace_back()函数可以提高代码的效率和可读性,减少对象的拷贝或移动,并支持完美转发,使代码更加简洁和灵活。

emplace支持参数包
在这里插入图片描述

定位new

内存池 显示的调用构造函数

lambda

在这里插入图片描述
在这里插入图片描述
简单的lambda函数

int mian()
{
	//两个数相加的lambda
	auto add1 = [](int a, int b)->int{return a + b; };
	cout << add1(1, 2) << endl;
	//省略返回值
	auto add2 = [](int a, int b){return a + b; };
	cout << add2(1, 2) << endl;
	//交换变量的lambda
	int x = 0,  y = 1;
	auto swap1 = [](int& x1, int& x2)->void {int tmp = x1; x1 = x2; x2 = tmp; };
	swap1(x, y);
	cout << x << ":" << y << endl;

	auto swap2 = [](int& x1, int& x2)
	{
		int tmp = x1; 
		x1 = x2; 
		x2 = tmp; 
	};
	swap2(x, y);
	cout << x << ":" << y << endl;

	//不传参数交换x,y  lambda  --捕捉列表  (默认捕捉过来的变量不能修改 加mutable)
	//auto swap3 = [x, y]()mutable   //无修改作用
	auto swap3 = [&x, &y]()   //传引用捕捉
	{
		int tmp = x;
		x = y;
		y = tmp;
	};
	swap3();
	cout << x << ":" << y << endl;

	return 0;
}

lambda作为sort的参数(之前用反函数对象或者类型实现)

	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._name <
	g2._name; });

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

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

相关文章

GNSS技术知识你知道多少?这些你或许还未掌握

GNSS信号频段 GNSS频谱图展示了不同的GNSS信号及其星座、载波频率、调制方案&#xff0c;以及所有这些信号在同一L波段频段内如何相互关联&#xff0c;是GNSS专业人员的必备工具&#xff0c;包括设计和开发GNSS系统的工程师&#xff0c;以及测试GNSS系统的工程师。 GNSS术语 …

如何清理电脑缓存垃圾

1、手动清理电脑缓存 C:\Users\yangguang\AppData\Local\Temp 注&#xff1a;yangguang 是自己电脑对应的用户目录 2、清理完后&#xff0c;电脑流畅了许多。

C++继承(2)——赋值转换、隐藏特性以及作用域

目录 一.子类和父类对象的赋值转换 子类对象赋值父类对象的另外两种方式&#xff1a; 总结&#xff1a; 二.父类与子类的作用域 1. 在继承体系中基类和派生类都有独立的作用域。 例&#xff1a; 2.作用域练习 练习1&#xff1a; 解决方法: 一.子类和父类对象的赋值转换 …

Reinforcement Learning with Code 【Code 2. Tabular Sarsa】

Reinforcement Learning with Code 【Code 2. Tabular Sarsa】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of Rei…

【C# 6.0】云LIS平台源码

基于云计算的区域LIS平台为医疗机构改善患者服务质量提供了强有力的支持&#xff0c;“以患者为核心”这一理念得到了充分实现&#xff0c;可以解决各医院LIS建设水平参差不齐的现状&#xff0c;并完善各医院内LIS系统的功能&#xff0c;实现数据标准统一、功能完善、性能可靠&…

VR全景旅游,智慧文旅发展新趋势!

引言&#xff1a; VR全景旅游正在带领我们踏上一场全新的旅行体验。这种沉浸式的旅行方式&#xff0c;让我们可以足不出户&#xff0c;却又身临其境地感受世界各地的美景。 一&#xff0e;VR全景旅游是什么&#xff1f; VR全景旅游是一种借助虚拟现实技术&#xff0c;让用户…

go env 配置(环境变量)说明

前提&#xff1a;已经安装好 golang 可正确的运行下面这段命令&#xff0c;来查看 go 的配置&#xff1a; go env 输出示例&#xff1a; 以上是我本地(windows)环境下输出的配置信息(环境变量) 我们这次就针对每个配置信息进行一个说明&#xff0c;具体到每个字段是什么意思…

浅谈Vue3 computed计算属性

什么是computed 官方给出的解释&#xff1a;接受一个 getter 函数&#xff0c;返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象 // 只读 function computed<T>(ge…

远程控制软件安全吗?一文看懂ToDesk、RayLink、TeamViewer、Splashtop相关安全机制

目录 一、前言 二、远程控制中的安全威胁 三、国内外远控软件安全机制 【ToDesk】 【RayLink】 【Teamviewer】 【Splashtop】 四、安全远控预防 一、前言 近期&#xff0c;远程控制话题再一次引起关注。 据相关新闻报道&#xff0c;不少不法分子利用远程控制软件实施网络诈骗&…

直播预告 | 开源运维工具使用现状以及可持续产品的思考

运维平台自上世纪90年代开始进入中国市场&#xff0c;曾形成以传统四大外企&#xff1a;IBM、BMC、CA、HP为代表的头部厂商&#xff0c;还有一众从网管起家的国内厂商。2010年前后&#xff0c;出现了以Zabbix、Nagios、Cacti为代表的开源工具&#xff0c;后来又陆续出现了Prome…

如何计算文本的困惑度perplexity(ppl)

前言 本文关注在Pytorch中如何计算困惑度&#xff08;ppl&#xff09;为什么能用模型 loss 代表 ppl 如何计算 当给定一个分词后的序列 X ( x 0 , x 1 , … , x t ) X (x_0, x_1, \dots,x_t) X(x0​,x1​,…,xt​), ppl 计算公式为&#xff1a; 其中 p θ ( x i ∣ x &l…

Ansible之playbook剧本编写

一、playbook的相关知识 1.playbook简介 playbook是 一个不同于使用Ansible命令行执行方式的模式&#xff0c;其功能更强大灵活。简单来说&#xff0c;playbook是一个非常简单的配置管理和多主机部署系统&#xff0c;不同于任何已经存在的模式&#xff0c;可作为一个适合部署复…

3.5千伏硅化碳(SiC)深埋式超结二极管

目录 相关知识研究了什么文章创新点研究方法文章的结论 相关知识 在科学和工程技术领域&#xff0c;SEM通常是扫描电子显微镜&#xff08;Scanning Electron Microscope&#xff09;的缩写。因此&#xff0c;在 “外延SEM横截面图” 中&#xff0c;SEM指的是扫描电子显微镜&am…

分享一些精选的开源框架与代码!

今天主要是收集并精选了一些自己所了解和学习过的优秀的嵌入式开源框架代码和项目&#xff0c;不太了解的就不推荐给大家了&#xff0c;因为开源的东西实在是太多了&#xff0c;鱼龙混杂&#xff0c;所以取其精华去其糟粕是迫在眉睫的大事~ 当然也不要总是沉浸在开源的东西之中…

手把手教你Pytest+Allure2.X定制报告详细教程,给自己的项目量身打造一套测试报告-02(非常详细)

简介 俗话说“人靠衣服马靠鞍”一个项目做的在好&#xff0c;没有一分的漂亮的测试报告有时候也是很难在客户那边验收的&#xff0c;今天就带你们解决这一难题。 前边一篇文章是分享如何搭建pytestAllure的环境&#xff0c;从而生成一份精美的、让人耳目一新的测试报告&#…

【Linux 网络】 HTTPS协议原理 对称加密 非对称加密 数字证书

HTTPS协议 HTTPS协议和HTTP协议的区别什么是“加密” 和“解密”加密和解密的小故事 为什么要进行加密&#xff1f;臭名昭著的“运营商劫持”事件 常见加密方式对称加密非对称加密 数据摘要数字签名 HTTPS工作过程探究方案 1 &#xff1a; 只使用对称加密方案2 &#xff1a; 只…

微信小程序交易体验分常见问题指引

小程序交易体验分是为保障小程序用户的交易体验&#xff0c;促进开发者向用户提供更好的服务&#xff0c;帮助开发者更好的评估自身服务水平的机制。平台将对开发者在其小程序的违规行为进行判定&#xff0c;根据违规行为的严重程度对该小程序扣减不同分值的交易体验分&#xf…

Excel快捷键F1-F9详解:掌握实用快捷操作,提升工作效率

Excel是广泛应用于办公场景的优质电子表格软件&#xff0c;然而&#xff0c;许多人只是使用鼠标点击菜单和工具栏来完成操作&#xff0c;而忽略了快捷键的威力。在本文中&#xff0c;我们将详解Excel中的F1-F9快捷键&#xff0c;帮助您掌握实用的快捷操作&#xff0c;提升工作效…

多组学背景下的基因调控网络推断

染色质、转录因子和基因之间的相互作用产生了复杂的调节回路&#xff0c;可以表示为基因调节网络&#xff08;GRNs&#xff09;。GRNs的研究有助于了解疾病中细胞身份是如何建立、维持和破坏的。GRN可以从实验数据——历史上的大量组学数据——或文献中推断出来。单细胞多组学技…

图形化分析工具

1.图形化之短距分析 2.图形化之温度、CPU频率分析 3.常用指令集合 4.常见fastboot指令集合 5.模块之自动化分析–此项功能需要后续不断完善