c++中的volatile和variant关键字详解

 更新时间:2022年01月25日 17:06:33   作者:fpcc  
大家好,本篇文章主要讲的是c++中的volatile和variant关键字详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下

一、两个长得有点像的变量

对volatile关键字,其实很多人只是能用,知道用到啥处,但其实应用的原理并不知道。在一些多线程的通信中,往往是这个关键字应用到的场所,很多人也是如此想的。但其实这个想法是不准确的。volatile这个关键字的目的最初是针对硬件IO操作的,防止访问IO操作中的缓存影响到真实的数据。但这个关键字的溢出效应是,多线程也可以应用这个原理(注意在多核和多CPU编程中有危险,但是在其它语言如Java中,得按具体的语言规范来决定),那么反而在硬件IO中的应用成了一种比较少的应用场景。
在c++17中,还有一个长得和它类似的联合体variant,如果有其它语言中var变量的使用,就大概明白了这是个啥玩意儿。既然是联合体,那么就明白了这个关键字的用处了,也就是说,它可以表示明确的类型定义,而在前面提到的std::any则不是。看一下在c++17中它的标准定义:

template <class... Types>
class variant;

之所以把它们两个搞在一起,是有的时候儿新手小菜鸟可能会把两个傻傻分不清。

二、二者的功能

类模板 std::variant 表示一个类型安全的联合体,它表示可以拥有其中的任何一个类型或者无值,它不能保有引用、数组或者void,如果表示一个空值,也要用std::variantstd::monostate 代替。同样,在默认构造时,默认保有联合体的第一个类型。面std::volatile则更多倾向于一个编译器的优化选项处理,它会防止变量被编译器缓存。正如前面所讲,这个在多线程中应用的比较多,但其实他更安全的应用其实是在硬件IO操作中。
这么看来,这二者的区别还是相当明显的,别看长得乍一看有点像,但还真不是一嘛事儿。只要写一回代码估计就记清楚了。或者简单的记忆成volatile是一个关键字,而variant是一个复合类型,是一个联合体,是一个类模板。

三、应用实例

看一个variant的例程:

#include <variant>
#include <string>
#include <cassert>
 
int main()
{
    std::variant<int, float> v, w;
    v = 12; // v 含 int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // 与前一行效果相同
    w = v; // 与前一行效果相同
 
//  std::get<double>(v); // 错误: [int, float] 中无 double
//  std::get<3>(v);      // 错误:合法下标值为 0 与 1
 
    try {
      std::get<float>(w); // w 含 int 而非 float :将抛出
    }
    catch (const std::bad_variant_access&) {}
 
    using namespace std::literals;
 
    std::variant<std::string> x("abc"); // 转换构造函数在无歧义时起作用
    x = "def"; // 转换赋值在无歧义时亦起作用
 
    std::variant<std::string, void const*> y("abc");
    // 传递 char const * 时转换成 void const *
    assert(std::holds_alternative<void const*>(y)); // 成功
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // 成功
}

volatitle这个关键字给一个判断的例程,就不给多线程的例程了,这玩意儿一般来说还是要小心使用,在多核,内存序未知的情况下,还是不用为妙,X86因为一些历史原因,用起来还是比较可以接受的:

#include <iostream>
#include <type_traits>
 
int main() 
{
    std::cout << boolalpha;
    std::cout << std::is_volatile<int>::value << '\n';
    std::cout << std::is_volatile<volatile int>::value  << '\n';
}

这个关键字对从Java转过来的开发人员可能有非常大的迷惑性,二者的理解意义还是有比较大的不同的。把内存序掌握好了,就知道为什么在X86的PC上跑一般没有问题的原因,如果还是无法清楚,就好好看看c++标准中对内存序的支持。这个一定要搞明白,搞不明白的话,可能不会影响到编程,但会影响到对标准的认知。

四、总结

俗话说:“看一遍不如写一遍”,这句话在计算机行业应该是非常合适的。计算机技术是一门理论科学与实践高度结合的技术,理论是源泉,实践是根本,互相反馈,不断迭代,这才是真正提高编程水平的王道。
努力吧,归来的少年

到此这篇关于c++中的volatile和variant关键字详解的文章就介绍到这了,更多相关c++ volatile和variant关键字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 共用体的定义与应用详细解析

    共用体的定义与应用详细解析

    共同体的定义类似结构体,不过共同体的所有成员都在同一段内存中存放,起始地址一样,并且同一时刻只能使用其中的一个成员变量
    2013-08-08
  • 汇编语言rep movsd 的使用详解

    汇编语言rep movsd 的使用详解

    rep movsd 每次ecx!=0便执行movsd ,然后ecx=ecx-1 movsd移动ds:[si] 到es:[di],在32位汇编下可以用esi代替si,edi代替di
    2013-09-09
  • 一文掌握C++ const与constexpr及区别

    一文掌握C++ const与constexpr及区别

    C++ 11标准中,const 用于为修饰的变量添加“只读”属性而 constexpr关键字则用于指明其后是一个常量,编译器在编译程序时可以顺带将其结果计算出来,而无需等到程序运行阶段,这样的优化极大地提高了程序的执行效率,本文重点介绍C++ const与constexpr区别介绍,一起看看吧
    2024-02-02
  • C语言操作符进阶教程(表达式求值隐式类型转换方法)

    C语言操作符进阶教程(表达式求值隐式类型转换方法)

    这篇文章主要为大家介绍了C语言操作符进阶教程(表达式求值隐式类型转换方法)
    2022-02-02
  • C语言 经典题目螺旋矩阵 实例详解

    C语言 经典题目螺旋矩阵 实例详解

    这篇文章主要介绍了C语言 经典题目螺旋矩阵 实例详解的相关资料,这里附有代码实例及实现效果图,需要的朋友可以参考下
    2016-12-12
  • C++实现银行排队系统

    C++实现银行排队系统

    这篇文章主要为大家详细介绍了C++实现银行排队系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 基于C语言编写一个简单的Web服务器

    基于C语言编写一个简单的Web服务器

    C语言可以干大事,这篇文章主要为大家详细介绍了如何基于C语言可以完成一个简易的Web服务器,希望这篇文章会帮你你对C语言有更深入的理解
    2024-03-03
  • 使用C++实现跨进程安全的文件读写锁

    使用C++实现跨进程安全的文件读写锁

    在多进程系统中,文件的并发读写可能导致数据竞争、文件损坏等问题,为了确保多个进程能够安全地访问同一文件,我们需要使用文件锁,本文将介绍如何使用 C++ 实现文件锁,并确保文件的并发读写操作是安全的,需要的朋友可以参考下
    2025-02-02
  • C++文件关键词快速定位出现的行号实现高效搜索

    C++文件关键词快速定位出现的行号实现高效搜索

    这篇文章主要为大家介绍了C++文件关键词快速定位出现的行号实现高效搜索,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 举例讲解C语言链接器的符号解析机制

    举例讲解C语言链接器的符号解析机制

    链接器的工作主要分为两个阶段:符号解析和重定位,符号解析的功能是将每个模块符号引用绑定到一个确切的符号定义,这里我们就来举例讲解C语言链接器的符号解析机制
    2016-05-05

最新评论