boost-數據類型之auto、any、tuple、variant


1、auto、decltype

  auto是C++11中的關鍵字,它可以通過類型推導自動得到變量或對象的類型,需要注意的是auto會忽略引用,因為引用其實就代表原對象:

#include <vector>
#include "boost/assign.hpp"
using namespace boost::assign;

int main()
{
    auto i = 10;
    auto f = 12.34;
    auto s = string("abc");
    cout << i << ", " << f << ", " << s << endl;
    int num = i;
    double d = f;
    string str = s;

    vector<int> vc = list_of(1) (2) (3);
    auto iter = vc.begin();
    auto iterEnd = vc.end();
    for (; iter != iterEnd; iter++)
    {
        cout << *iter << endl;
    }

    return 0;
}
View Code

  auto還可以配合C++11中的“尾置返回”,尾置返回”適用於返回類型比較復雜的函數。如以下func函數的返回類型為指向包含三個int元素的數組的地址:

auto func()->int(*)[3]
{
    static int ary[3];
    return &ary;
}
View Code

  以上代碼其實與下面代碼效果相同:

typedef int(*pAry)[3];
pAry func2()
{
    static int ary[3];
    return &ary;
}
View Code

  auto還可以用在for循環中使代碼簡單:

    int ary[] = { 1, 2, 3 };
    for (auto e : ary)
    {
        std::cout << e << std::endl;
    }

    int ary[] = { 1, 2, 3 };
    for (auto& e : ary)
    {
        e = 0;
    }
    
    char* ary[] = { "c++", "java", "python" };
    for (auto* p : ary)
    {
        std::cout << p << std::endl;
    }
View Code

 如果我們希望從表達式中推斷出要定義變量的類型,但卻不想用表達式的值去初始化變量,那么可以使用decltype,需要注意的是如果decltype使用的變量加上一個括號的話那么decltype會返回對應的引用類型:

    int func(int i)
    {
        return i;
    }
    decltype(func(0)) num = 100; //num是int類型,不會調用func()
    
    std::vector<int> vc = { 1, 2, 3, 4, 5 };
    auto size = vc.size();
    for (decltype(size) i = 0; i < size; i++) // i是size_t類型
    {
        ;
    }

    int i = 100;
    decltype((i)) d = num; //d是int引用類型,其指向num
View Code

2、any

  any功能與auto類似,二者不同之處在於:auto是一個類似int、double、string的C++關鍵字,它不是一個類,所以沒有成員函數可調用,直接把他當做int、double、string這種關鍵字來使用。any是一個類,只能通過any_cast<>獲得any的實際內部值,而不能像auto定義的對象那樣直接使用它。

  any也可以用來存儲任意類型元素,如int、double、string、vector或自定義類型。它能夠存儲任意類型的原因是其構造函數和賦值函數opeartor=是模板函數,可以接收任意類型。any不是一個模板類,所以定義元素的時候不必使用<>,如any a = 10;
  需要注意的有兩點:
  在any存儲字符串的時候只能使用string,如any a = string("hello");,不能使用C風格的字符串,如:any a = "hello";
  如果保存動態內存指針類型,會引起內存泄露,解決方法是使用智能指針shared_ptr來指向動態內存,如:shared_ptr<char> ptrSmart(new char[10]); any a = ptrSmart; 

  any的出現讓C++仿佛變成了一種弱類型的動態語言。
  動態語言:運行期間才做數據類型檢查的語言,即編譯的時候不知道每一個變量的類型,如php、Ruby
  靜態語言:編譯期間做數據類型檢查的語言,即編譯的時候就知道每一個變量的類型,如C/C++、C#、JAVA
  強類型:變量一定是有類型的, 且變量/對象的類型一旦確定, 其類型不再允許更改,如C/C++/Java/C#
  弱類型: 變量的類型概念很弱或者沒有類型的概念, 不同變量的類型可以更改. 如php、Ruby
  類型安全:的代碼不會試圖訪問自己沒被授權的內存區域,如C/C++就不是類型安全的,兩個不同類型的指針之間可以通過dynamic_cast進行轉換。

  any::empty()判斷any是否為空
  any::type()獲得內部對象的類型,是一個標准type_info類的引用

  any_cast<>()獲得any內部對象值或內部對象指針或內部對象的引用

#include <vector>
#include "boost/any.hpp"
#include "boost/assign.hpp"
using namespace boost::assign;


template <typename T> 
bool match_type(boost::any& a)
{
    if (a.empty())
        return false;

    return typeid(T) == a.type();
}

template<typename T> 
T get_value(boost::any& a)
{
    BOOST_ASSERT(match_type<T>(a));

    return boost::any_cast<T>(a);
}

template <typename T> 
T* get_pointer(boost::any& a)
{
    BOOST_ASSERT(match_type<T>(a));

    return boost::any_cast<T>(&a);
}

template <typename T> 
T& get_reference(boost::any& a)
{
    BOOST_ASSERT(match_type<T>(a));

    return boost::any_cast<T&>(a);
}

int main()
{
    boost::any a = 10;

    int iNum = get_value<int>(a);//獲得a的內部元素
    cout << iNum << endl;

    int * p = get_pointer<int>(a);//獲得a內部元素的指針
    cout << *p << endl;

    get_reference<int>(a) = 5;//獲得a內部元素引用,引用可以被當做左值來使用
    cout << *p << endl;

    if (match_type<int>(a))//判斷a內部元素類型是否為int
        cout << "true" << endl;

    return 0;
}
View Code

3、tuple

  tuple類型類似於std::pair,pair只支持包含兩種類型的元素,tuple可以支持包含多個不同類型的元素,比如將其用於多個返回值的函數的話比使用struct更方便,一個簡單的使用示例如下:

#include <cstdio>
#include <string>
using std::string;
#include "boost/tuple/tuple.hpp"

boost::tuple<int, double, string> func()
{
    int i = 1;
    double d = 5.0;
    string s("hello");
    boost::tuple<int, double, string> tupleCombin(i, d, s);

    return tupleCombin;
}

int main()
{
    boost::tuple<int, double, string> tupleCombin = func();
    int i = tupleCombin.get<0>();
    double d = tupleCombin.get<1>();
    string s = boost::get<2>(tupleCombin);

    return getchar();
}
View Code

4、variant

  variant是一種增強的union,C/C++中union只能持有POD(普通數據類型),而不能持有如string、vector等復雜類型,boost的variant則沒有這個限制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM