C++Cherno 学习笔记day19 [76]-[80] std::optional、variant、any、如何让C++及字符串运行得更快

一、如何处理OPTIONAL数据 std::optional

std::optional C++17
数据是否存在是可选的

#include <iostream>
#include <fstream>
#include <optional>

std::optional<std::string> ReadFileAsString(const std::string& filepath)
{
	std::ifstream stream(filepath);
	if (stream)
	{
		std::string result;
		// read file
		stream.close();
		return result;
	}
	return {};
}

int main()
{
	std::optional<std::string> data = ReadFileAsString("data.txt");
	if (data.has_value())
	{
		std::cout << "File read successfully!\n";
	}
	else
	{
		std::cout << "File could not be opened\n";
	}
	std::cin.get();
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#include
std::optional function(param){statement; return type;}
auto result = function();
1: result.has_value()判断数据是否存在, 通过result.value()获取数据
2: result.value_or(xxx)其中xxx作为默认值,如果存在数据返回数据,不存在返回xxx
3:通过if (result)判断数据是否存在

注: 使用场景—目标值可能存在也可能不存在,比如读取文件并返回内容,可能读取成功有数据,读取成功无数据,读取不成功。

二、单一变量存放多类型的数据 std::variant

C++17的特性
C++17新的标准库给我们的类
std::variant
variant本质上就像类型安全的联合体union

#include <iostream>
#include <variant>

int main()
{
	std::variant<std::string, int> data;

	std::cout << sizeof(int) << "\n";
	std::cout << sizeof(std::string) << "\n";
	std::cout << sizeof(data) << "\n";

	data = "wm";
	std::cout << std::get<std::string>(data) << "\n";
	//data.index();// 0
	if (auto* value = std::get_if<std::string>(&data))
	{
		std::string& v = *value;
	}
	else
	{

	}
	data = 2;

	std::cout << std::get<std::string>(data) << "\n";
	std::cout << std::get<int>(data) << "\n";

	std::cin.get();
}

在这里插入图片描述

它是为你创建了一个结构体或类。
它只是将这两种数据类型存储为那个类或结构体中的成员

std::variant(C++17引入)和传统的union(C语言继承的特性)都用于存储不同类型的值,但它们在设计、安全性和功能上有显著差异。

从技术上讲,union仍然是更有效率和更好的
然而,variant更加类型安全,不会造成未定义行为,你应该使用它,
除非你做的是底层优化,把内存大小保持在一个较低的位置,不管是什么原因,比如CPU处理
或者只是因为你想使用尽可能少的内存

但是,如果您是在桌面平台上,您可以自由地使用更多的内存
和更多的处理能力,那么std::variant在技术上更安全
在这里插入图片描述
在这里插入图片描述

#include
std::variant<type1, type2> data;
data = type1(xxx)
类似于union,type1与type2表示存储的数据类型。

读取:
1: std::get(data)
2: auto *value = std::get_if(type)(&data)
注:类型安全

在这里插入图片描述

三、如何存储任意类型的数据 std::any

void指针
std::any

variant和any的区别

variant需要你列出类型

这和它们的存储方式有关,variant只是一个类型安全的union,
意思是它把所有的数据都存储在一个union里

small types 小类型
它只是把它们存储为一个Union,这意味着对于小类型small type来说,
它的工作方式与variant完全相同

如果你有一个大的类型,它会带你进入大存储空间的void*,
在这种情况下,它会动态分配内存
动态分配内存不利于性能

总结一下这是如何工作的,如果你在小型类型上使用variant或any。
比如int,float。比如一个用于类的vector或类似的东西
比如math库等等,都没问题

它们会以完全相同的方式工作

如果你需要更多的存储空间,std::any会动态分配,
但是std::variant不会

所以换句话说,除了更加类型安全和有一点限制性(这是一件好事)之外,std::variant在处理较大数据时也会执行得更快,而这些数据又需要避免动态内存分配

四、如何让C++运行得更快

如何通过多线程提高性能
C++11的引入 std::asnyc futures

五、如何让C++字符串更快

#include <iostream>
#include <string>

static uint32_t s_AllocCount = 0;

void* operator new(size_t size)
{
	s_AllocCount++;
	std::cout << "Allocating " << size << "bytes\n";
	return malloc(size);
}

void PrintName(const std::string& name)
{
	std::cout << name << std::endl;
}

int main()
{
	std::string name = "Yan Chernikov";
	PrintName(name);
	std::cout << s_AllocCount << " allocations" << std::endl;

	std::cin.get();
}

在这里插入图片描述

#include <iostream>
#include <string>

static uint32_t s_AllocCount = 0;

void* operator new(size_t size)
{
	s_AllocCount++;
	std::cout << "Allocating " << size << "bytes\n";
	return malloc(size);
}

void PrintName(const std::string& name)
{
	std::cout << name << std::endl;
}

int main()
{
	std::string name = "Yan Chernikov";
	std::string firstName = name.substr(0, 3);
	std::string lastName = name.substr(4, 9);

	PrintName(firstName);

	std::cout << s_AllocCount << " allocations" << std::endl;

	std::cin.get();
}

在这里插入图片描述
有一种很简单的方法,可以修改现有代码,将分配减少到一个
最后我们会删除所有这些分配,也就是0个分配

当你在优化的时候,只要看看这个程序,你只需要看看你在做什么,因为在很多情况下,只要看看数据你就能找到优化它的方法

换句话说,我在创建一个窗口,一个进入现有内存的小视图,
而不是分配一个新的字符串,用substrO创建一个新的字符串

我不需要这些,因为我想要的只是一个窗口的视图,到一个已有的、有自己内存的字符串

视图:一种不复制的数据窗口

尽量不使用string使用const char*或string_views

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值