cpp学习日记10(只是记录给未来的自己看的)

C++中的structured binding(结构化帮定)

#include"pch.h"

std::tuple<std::string, int,int> CreatePerson(){
	return { "yueke",5,8 };
}


int main()
{
	auto person = CreatePerson();
	std::cout << std::get<0>(person) << std::endl;//输出yueke

	int age, h;
	std::string name;

	std::tie(name, age, h) = CreatePerson();//将tuple赋给已有的变量上

	std::cin.get();
}


C++17中引入新特性,可以在将函数返回为tuple、pair、struct等结构时且赋值给另外变量的时候,直接得到成员。

#include"pch.h"

std::tuple<std::string, int,int> CreatePerson(){
	return { "yueke",5,8 };
}


int main()
{
	auto[name, age, h] = CreatePerson();//在c++17里面可以直接这样子写了,方便地返回多个返回值

	std::cin.get();
}

它的优势是,我们可以不再为了一次多返回值就创建一个只会使用一次的结构体了。

如何处理optional数据

比如在读取文件内容的时候,往往需要判断读取是否成功,常用的办法是传入一个引用变量,或判断返回std::string是否为空。
如果用optional对象作为函数返回值,那么我们将很容易地解决引言中所述的问题。如果函数失败,则返回std::nullopt表示没有有效返回值,否则就直接返回计算值。这样代码将更将简介,可靠。


std::optional<int> findStudent(const std::map<std::string, int> & students, const std::string & name)
{
	if (students.find(name) == students.end())
	{
		return std::nullopt;
	}
	return students[name];
}
//使用
auto studentId = findStudent(students, "Bob");

#include<iostream>
#include<optional>
#include<map>
#include<vector>

std::map<std::string, int> students;
std::vector<std::pair<std::string,int>> stu = { {"Tom",1},{"Bob",18},{"Amy",3},{"Joy",4},{"May",5} };

std::optional<int> findStudent(std::map<std::string,int>& student, const std::string& name)
{
	for (auto p : stu)
	{
		students.insert(p);
	}
	if (students.find(name) == students.end())
	{
		return std::nullopt;
	}
	return students[name];
}
int main()
{
	auto studentId = findStudent(students, "Bob");
	std::cout << studentId.value_or(80) << std::endl;
}

C++一个变量多种类型

C++17引入一种可以容纳多种类型变量的结构,std::variant

#include"pch.h"

std::tuple<std::string, int,int> CreatePerson(){
	return { "yueke",5,8 };
}


int main()
{
	std::variant<std::string, int> data;//data既可以是string又可能是int
	data = "yueke";
	data.index();//返回索引值表示当前的data是哪个数据类型,以索引表示,比如这里,会返回1
	auto* value = std::get_if<int>(&data);//检查现在data是不是int类型,如果不是,就会返回一个空指针
	//如果是,则会返回那个值的指针
	std::cout << std::get<std::string>(data) << std::endl;//把字符串取出来
	data = 5;
	std::cout << std::get<int>(data) << std::endl;//把整数取出来
	//如果你的data还是一个整数而你用get以字符串方式取的话,那么将会给你抛出一个异常
	std::cin.get();
}


std::variant的大小是<>里面的大小之和(对于基本类型是这样,加上string和类之后就变了),与union不一样,union的大小是类型的大小最大值。虽然variant似乎更浪费内存,但是人家type safe,因此应该用它除非真的要节省内存。

我们可以通过variant做到tuple运行期索引,(std::get<>依赖一个编译器的变量,所以以前我们很难做到运行期索引):

std::any()

这里主要引出std::any,也是C++17引入的可以存储多种类型变量的结构,其本质是一个union,但是不像std::variant那样需要列出类型。

#include <iostream>
#include <any>

// 此处写一个new的函数,是为了断点,看主函数里面哪里调用了new,来看其堆栈
void* operator new(size_t size)
{
	return malloc(size);
}

int main()
{
	std::any data;
	data = 2;
	data = std::string("hbh");
	// 注意,左边是引用,那么右边的cast也要是引用来对应
	std::string& s = std::any_cast<std::string&>(data);
	std::cout << s << std::endl;
	std::cin.get();
}


当小的类型的时候,会绑成一个union,然而当类型足够大的时候就只能动态分配内存了,这是很耗时的。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值