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; }
auto还可以配合C++11中的“尾置返回”,尾置返回”适用于返回类型比较复杂的函数。如以下func函数的返回类型为指向包含三个int元素的数组的地址:

auto func()->int(*)[3] { static int ary[3]; return &ary; }
以上代码其实与下面代码效果相同:

typedef int(*pAry)[3]; pAry func2() { static int ary[3]; return &ary; }
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; }
如果我们希望从表达式中推断出要定义变量的类型,但却不想用表达式的值去初始化变量,那么可以使用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
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; }
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(); }
4、variant
variant是一种增强的union,C/C++中union只能持有POD(普通数据类型),而不能持有如string、vector等复杂类型,boost的variant则没有这个限制。