📜  std :: C++中的任何类

📅  最后修改于: 2021-05-30 11:07:33             🧑  作者: Mango

anyC++ 17的最新功能之一,它提供了一个类型安全的容器来存储任何类型的单个值。用外行的话来说,它是一个容器,允许人们在其中存储任何值而不必担心类型安全。它通过模仿类似于.NET / Java的对象类型或C语言中的void *类型的行为,作为对C++的扩展。它是基于boost :: any设计的,可在“ any”头文件中使用。

句法:

any var= value/object; 

其中的价值类似于“ 17”或“ Hello World”

初始化任何:

可以使用以下三种不同方式来构造任何一个:

  1. 复制初始化

    句法:

    any variable_name = object/value;
    
  2. 参数化的构造函数/括号初始化程序。

    句法:

    any variable_name ( object/value);
    
  3. 使用赋值运算符

    句法:

    any variable_name;
    variable_name= object/value;
    

    将any_var值转换为其原始类型:

    必须使用any_cast (any_var)将any_var值转换为其原始类型。如果存储值的类型不同于尝试转换的类型,则编译器将抛出“ bad_any_cast ”异常。

    注意:强制转换期间的类型必须与原始类型完全相同。投放期间不会自动升级或降级。因此,在将值转换为原始类型时必须格外小心。

    一个简单的例子(说明任何一个的构造/读取值)

    #include 
    #include 
    #include 
    using namespace std;
      
    int main()
    {
        try {
      
            // Integer 42:  Using the copy initialisation
            any value = 42;
            cout << "\n Value: "
                 << any_cast(value);
      
            // Using the assignment operator
            // to store a string
            value = "Hello World";
            cout << "\n Value: "
                 << any_cast(value);
      
            // Using the parametrized constructor
            any val(19.0);
            cout << " \n Value: "
                 << any_cast(val);
      
            any val_brace{ string("Brace Initialisation") };
            cout << " \n Value: "
                 << any_cast(val_brace);
        }
      
        catch (bad_any_cast& e) {
            cout << "\n"
                 << e.what();
        }
        return 0;
    }
    

    输出:

    Value: 42 
     Value: Hello World 
     Value: 19 
     Value: Brace Initialisation
    

    成员功能:

    1. emplace :更改包含的对象,直接构造新对象
    2. reset :销毁包含的对象(调用对象的析构函数)
    3. has_value :检查“ any_variable”是否在其中包含一个值
    4. type :返回所包含值的类型ID

    让我们详细地逐一查看这些方法:

    • emplace: emplace成员函数类似于赋值运算符,用于用新对象更改包含的对象。

      程序:

      // C++ program to demonstrate
      // emplace() method of any class
        
      #include 
      #include 
      #include 
        
      int main()
      {
          try {
              any value = 4.2;
              cout << " \n Value:  "
                   << any_cast(value);
        
              value.emplace(44);
              cout << " \n Value:  "
                   << any_cast(value);
          }
          catch (bad_any_cast& e) {
              cout << "\n"
                   << e.what();
          }
          return 0;
      }
      

      输出:

      Value:  4.2 
      Value:  44
      
    • reset:通过调用包含对象的析构函数来销毁包含对象。

      程序:

      // C++ program to demonstrate
      // reset() method of any class
        
      #include 
      #include 
      #include 
        
      int main()
      {
          try {
              any var = 4.2;
              cout << " \n Value:  "
                   << any_cast(var);
        
              var.reset();
              if (!var.has_value())
                  cout << " \n No value found in var variable";
          }
          catch (bad_any_cast& e) {
              cout << "\n"
                   << e.what();
          }
          return 0;
      }
      

      输出:

      Value:  4.2 
      No value found in var variable
      
    • has_value:此成员函数用于检查对象是否包含值

      程序:

      // C++ program to demonstrate
      // has_value() method of any class
        
      #include 
      #include 
      #include 
        
      int main()
      {
          try {
              any var = 9.5;
              cout << " \n Value:  "
                   << any_cast(var);
        
              if (var.has_value())
                  cout << " \n Value found of type "
                       << var.type().name();
          }
        
          catch (bad_any_cast& e) {
              cout << "\n"
                   << e.what();
          }
          return 0;
      }
      

      输出:

      Value:  9.5 
       Value found of type d
      
    • type:此成员函数返回type_info结构,该结构可用于获取存储对象的属性。

      程序:

      // C++ program to demonstrate
      // type() method of any class
        
      #include 
      #include 
      #include 
        
      int main()
      {
          try {
              any var = 12.0f;
              cout << " \n Type:  "
                   << var.type().name();
        
              var = "Hello World";
              cout << " \n Type:  "
                   << var.type().name();
          }
          catch (bad_any_cast& e) {
              cout << "\n"
                   << e.what();
          }
          return 0;
      }
      

      输出:

      Type:  f 
      Type:  PKc
      

    任何用途

    典型用途包括

    1. 在库中,当库类型必须在不知道可用类型集的情况下保留或传递任何内容时。
    2. 讯息传递
    3. 实施解析器库。 JSON解析器
    4. 用户界面:控件可能包含任何内容
    5. 实体组件系统。

    任何方法的主要优点之一是可以用void *进行可行的替换。 void *功能有限(仅存储指针类型),被认为是不安全的模式。

    错误处理:

    关于任何类的错误处理,有两种选择:

    1. 使用异常: bad_any_cast是类型不匹配时any_cast的值返回形式引发的异常。

      例子:

      // C++ program to demonstrate
      // using exceptions of any class
        
      #include 
      #include 
      #include 
        
      int main()
      {
          try {
              any var = 12.0f;
        
              cout << " \n Value:  "
                   << any_cast(var);
          }
        
          catch (bad_any_cast& e) {
              cout << "\n"
                   << e.what();
          }
          return 0;
      }
      

      输出

      Value:  
      bad any_cast
      
    2. 返回指针:如果在编译器中禁用了异常机制,则返回指针非常有用。如果强制转换成功,则any_cast的此特定重载将返回包含对象的指针,并返回nullptr

      例子:

      // C++ program to demonstrate
      // returning pointer of any class
        
      #include 
      #include 
      #include 
      using namespace std;
        
      int main()
      {
          any var = 12.0f;
        
          // Special Overload of any_cast
          auto* tval = any_cast(&var);
          if (!tval) {
        
              // Type-mismatch
              cout << " \n Bad_any_cast ";
          }
          else {
        
              // Value of the object
              cout << " \n Value:  "
                   << *tval;
          }
        
          return 0;
      }
      

      输出:

      Value:  12
      

    内存注意事项

    尽管任何语言都提供了很大的灵活性,但是任何语言的主要问题是额外的动态内存分配。由于容器不知道所包含的对象,因此任何情况下都必须进行动态分配。

    但是根据标准,实现应避免为较小的包含值使用动态分配的内存。示例:构造的对象仅包含一个int。此类小对象优化应仅应用于is_nothrow_move_constructible_v为true的类型T。

    这通常意味着编译器必须使用小型缓冲区优化(SBO),其中必须保留一定数量的内存才能包含该类型。

    从上表中可以看到,在某些情况下为SBO保留的内存可能高达64字节! (MSVC-64位)。这意味着任何对象的每个对象都将需要保留64个字节的内存,即使对象很小,这也是相当大的内存开销。

    尽管在C++中,任何功能都是非常强大的功能。就内存而言,这会带来相当大的开销

    要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”