锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C++开源社区 / C++17新增数据类型byte、variant、optional和any

服务方向

人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
量化预测
股票离线分析软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发

联系方式

固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品原创,禁止转载和任何形式的非法内容使用,违者必究。点名“简易百科”和“闲暇巴”盗用锐英源原创内容。


C++17新增数据类型byte、variant、optional和any


C++17新增数据类型byte、variant、optional和any的第一感觉是C++越来越不像强类型语言了,这个转变可能初学者不好接受,variant像联合又像MFC的COleVariant,但又不是,optional是可有可无的意思,any就彻底像C#的Type基类了,总之觉得C++标准团队也是在学其它语言,让C++与时俱进,但变的越来越复杂,复杂是因为旧的原始模式不能废除,旧的模式和新的模式就像两条路,不过新增数据类型有适用场合,大家也只有坚持学习了。

在 C++17 中,标准库中添加了许多新的和有用的数据类型,其中一些源自 Boost。

std::byte

std::byte表示单个字节。开发人员传统上使用 char(signed or unsigning) 来表示字节,但现在有一种类型不仅可以是字符或整数。

但是,std::byte可以转换为整数,反之亦然。该std::byte类型旨在与数据仓库交互,不支持算术运算,尽管它支持按位运算。

为了说明上述内容,我们来看一下以下代码:


#include <iostream>
#include <cstddef>

void PrintValue(const std::byte& b) {
std::cout << "current byte value is " << std::to_integer<int>(b) << std::endl;
}

int main() {
std::byte bt {2};
std::cout << "initial value of byte is " << std::to_integer<int>(bt) << std::endl;
bt <<= 2;
PrintValue(bt);
}

std::variant 是一个类型安全的联合,它包含给定时间的替代类型之一的值(这里不能有引用、数组或 'void')。

一个简单的示例:假设有一些数据,其中某个公司可以表示为 an ID或 a string,并带有该公司的全名。此类信息可以使用包含std ::variant无符号整数或 string来表示。通过将整数分配给 std::variable,我们设置值,然后我们可以使用 std::get提取它,如下所示:


#include <iostream>
#include <variant>

int main() {
std::variant<uint32_t, std::string> company;
company = 1001;

std::cout << "The ID of company is " << std::get<uint32_t>(company) << std::endl;
return 0;
}

如果我们尝试使用不是以这种方式定义的成员(例如std::get<std::string>(company),),程序将引发异常。

为什么使用std::variant而不是通常的联合?这主要是因为联合在语言中存在主要是为了与 C 兼容,并且不适用于非 POD 类型的对象。

这尤其意味着,将具有自定义复制构造函数和析构函数的成员放在联合中并不容易。对于 std::variant,则没有此类限制。

std::optional

std::optional类型是一个对象,它可能包含也可能不包含值;当函数无法返回值时,此对象可用作函数的返回值,这很有用且方便;然后,它用作null指针的替代项。当使用 optional 时,我们获得了一个额外的优势:现在函数失败的可能性直接在声明中明确表示,并且由于我们必须从 optional 中提取值,因此我们意外使用null值的概率大大降低。

让我们看一下以下示例:


#include <iostream>
#include <string>
#include <optional>

std::optional<int> StrToInt(const std::string& s) {
try {
int val = std::stoi(s);
return val;
}
catch (std::exception&) {
return {};
}
}

int main() {

int good_value = StrToInt("689").value_or(0);
std::cout << "StrToInt(""689"") returns " << good_value << std::endl;

int bad_value = StrToInt("hfjkhjjkgdsd").value_or(0);
std::cout << "StrToInt(""hfjkhjjkgdsd"") returns " << bad_value << std::endl;

return 0;
}

上面的示例显示了一个尝试将StrToInt转换为整数的函数。通过返回std::optional,该StrToInt函数留下了可以传递 invalid string的可能性,该 invalid string无法转换。在main中,我们使用value_or()函数从std::optional中获取值,如果函数失败,则返回默认值零(如果转换失败)。

std::any

C++17 的另一个新增功能是std::any类型 . std::any为任何类型的单个值提供类型安全容器,并提供允许您执行类型安全验证的工具。

让我们看一下以下示例:

C++
#include <any>
#include <utility>
#include <iostream>
#include <vector>

int main() {

std::vector<std::any> v { 10, 20.2, true, "Hello world!" };

for (size_t i = 0; i < v.size(); i++) {
auto& t = v[i].type();

if (t == typeid(int)) {
std::cout << "Index of vector : " << i << " Type of value : 'int'\n";
}
else if (t == typeid(double)) {
std::cout << "Index of vector : " << i << " Type of value : 'double'\n";
}
else if (t == typeid(bool)) {
std::cout << "Index of vector : " << i << " Type of value : 'bool'\n";
}
else if (t == typeid(char *)) {
std::cout << "Index of vector : " << i << " Type of value : 'char *'\n";
}
}

std::cout << "\n std::any_cast<double>(v[1]) = " << std::any_cast<double>(v[1])
<< std::endl;

return 0;
}

在上面的代码中,在循环中,我们传递 std::vector<std::any>元素 .在每次迭代中,我们提取向量的一个元素,然后尝试确定std::any值的实际类型。

请注意,std::any_cast<T>(val) 返回在'val' 中内部值T的副本。如果我们需要获取引用以避免复制复杂对象,则需要使用any_cast<T&>(val) construct。

但是double类型不是一个复杂的对象,因此我们可以负担得起一个副本。这正是我们在上面代码的倒数第二行所做的,其中我们访问了 v [1] double类型的对象。

any就是MFC里的COleVariant,可以保存所有类型的数据,有VT_TYPE属性成员。

友情链接
版权所有 Copyright(c)2004-2024 锐英源软件
统一社会信用代码:91410105098562502G 豫ICP备08007559号 最佳分辨率 1440*900
地址:郑州市金水区文化路97号郑州大学北区院内南门附近