auto
1.简介
在 C++98 中,auto 是一个存储类型的说明符,表明变量是局部自动存储类型,但是在局部域中定义的局部变量默认就是自动存储类型,所以 auto 也就没有实际的用处了。于是,C++11 将 auto 原来的用法改为实现自动类型推断。
2.使用
auto 的使用示例如下:
double func()
{
return 10.4;
}
int main()
{
int a = 10;
auto b = a;
auto c = ']';
auto d = func();
auto p = &a;
auto pf = memcpy; // memcpy是函数指针
vector<int> v;
auto vv = v;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(p).name() << endl;
cout << typeid(pf).name() << endl;
cout << typeid(vv).name() << endl;
return 0;
}
注:使用语句
cout << typeid(变量名).name() << endl;
可以打印查看变量的类型。
上面代码的结果是:
auto 的使用有一个前提:必须对变量进行初始化。因为在编译阶段,编译器需要根据初始化表达式的类型来推导变量实际的类型。因此 auto 并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将 auto 替换为变量实际的类型(比如语句auto e;
就无法通过编译,因为使用auto定义变量时没有对其进行初始化)。
auto 还有很多使用细则,这里没有进行展开。
3.常见用法
虽说变量类型声明的简化不是必要的,但是在某些情况下(尤其是在使用模板时),变量类型的声明比较长,不便于程序的书写和阅读,因而在代码上下文便于理解的前提下,往往使用 auto 来简化。
int main()
{
std::map<std::string, std::string> dict = { { "left", "左边" }, { "insert", "插入" } };
//使用map的迭代器
//写法1:
std::map<std::string, std::string>::iterator it = dict.begin();
//写法2:
auto it = dict.begin();
/*这两种写法均可,但相对而言明显是写法2更加简洁*/
return 0;
}
auto 还有其它常见的用法,比如和范围for、lambda表达式等进行配合使用。
vector<string> v = { "abc", "def", "ghi", "jkl" };
//范围for
for (auto& e : v)
{
cout << e << endl;
}
cout << endl;
//lambda表达式
auto test = [](int a, double b)->double {return a * b; };
cout << test(2, 3.14) << endl;
decltype
1.简介
decltype 的作用是根据表达式的实际类型推演出变量的定义类型。
decltype 反映其具有获取表达式的“声明类型”(Declared Type)的功能。
2.使用
int main()
{
const int x = 1;
decltype(x) y = 4; // y的类型是const int
double z = 3.3;
decltype(x * z) ret; // ret的类型是double
decltype(&x) p; // p的类型是const int*
return 0;
}
3.常见用法
需要定义一个跟 A 一样类型的对象 B,但 A 的类型不方便写出来或写出来比较复杂,这时可以用 decltype 。
vector<string> func(string s, map<string, string> m)
{
// ...
}
int main()
{
//定义函数指针pf
//写法1:
vector<string> (*pf)(string, map<string, string>) = func;
//写法2:
decltype(&func) pf = func;
/*pf的类型是函数指针,即:vector<string> (*) (string, map<string, string>)
两种写法均可,但明显写法2更简洁*/
//定义函数指针vector
vector<decltype(pf)> v;
/*vector是类模板,在定义时需要写出参数类型,而decltype可以获取参数类型*/
/*写成 vector< vector<string> (*) (string, map<string, string>) > v; 也可以,但太过复杂*/
return 0;
}
std::map<std::string, std::string> dict = { { "left", "左边" }, { "insert", "插入" } };
auto it = dict.begin(); //由于该变量的类型声明比较繁琐,所以用auto简化了
vector<decltype(it)> v; //但现在需要auto推导对象的类型,这时可用decltype
有些类型由模板参数决定,但难以(甚至不可能)表示该类型,这时可以用 decltype 。
template<class T>
void test(T x)
{
decltype(x) ret;
// ...
}
template<class T1, class T2>
void Func(T1 a, T2 b)
{
decltype(a * b) ret;
// ...
}
【上期文章】
C++11:列表初始化