自动类型推导 auto
auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以简化我们的编程工作;
auto是在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响;
另外,似乎auto也并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。
auto a; // 错误,auto是通过初始化表达式进?类型推导,如果没有初始化表达式,就无法确定a的类型
auto i = 1;
auto d = 1.0;
auto str = "Hello World"
auto ch = 'A'
auto对引用的推导默认为值类型,可以指定引用修饰符设置为引用:
int x = 5;
int & y = x;
auot z = y ;
// z 为int
auto & z = y;
// z的类型为 int&
对指针的推导默认为指针类型,当然,也可以指定*修饰符(效果一样):
int *px = &x;
auto py = px;
auto*py = px;
推导常量
const int *px = &x;
auto py = px;
//py的类型为 const int *
const auto py = px ;
//py的类型为const int *
萃取类型 decltype
decltype实际上有点像auto的反函数,使用auto可以用来声明一个指定类型的变量,而decltype可以通过一个变量(或表达式)得到类型;
#include int main() { int x = 5; decltype(x) y = x; //等于 auto y = x; const std::vector v(1); auto a = v[0]; // a has type int decltype(v[1]) b = 1; // b has type const int&, the return type of // std::vector::operator[](size_type) const auto c = 0; // c has type int auto d = c; // d has type int decltype(c) e; // e has type int, the type of the entity named by c decltype((c)) f = c; // f has type int&, because (c) is an lvalue decltype(0) g; // g has type int, because 0 is an rvalue } |
有没有联想到STL中的萃取器?写模版时有了这个是不是会方便很多;
返回类型后置语法 Trailing return type
C++11支持返回值后置
例如:
int adding_func(int lhs, int rhs);
可以写为:
auto adding_func(int lhs, int rhs) -> int
auto用于占位符,真正的返回值在后面定义;
这样的语法用于在编译时返回类型还不确定的场合;
比如有模版的场合中,两个类型相加的最终类型只有运行时才能确定:
template
auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs)
{return lhs + rhs;}
cout << adding_func<double,int>(dv,iv) << endl;
auto用于占位符,真正的返回值类型在程序运行中,函数返回时才确定;
不用auto占位符,直接使用decltype推导类型:
decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs)
这样写,编译器无法通过,因为模版参数lhs和rhs在编译期间还未声明;
当然,这样写可以编译通过:
decltype( (*(Lhs*)0) + (*(Rhs*)0) ) adding_func(const Lhs &lhs, const Rhs &rhs)
但这种形式实在是不直观,不如auto占位符方式直观易懂;
空指针标识 nullptr
空指针标识(nullptr)(其本质是一个内置的常量)是一个表示空指针的标识,它不是一个整数。这里应该与我们常用的NULL宏相区别,虽然它们都是用来表示空置针,但NULL只是一个定义为常整数0的宏,而nullptr是C++11的一个关键字,一个内建的标识符。
nullptr和任何指针类型以及类成员指针类型的空值之间可以发生隐式类型转换,同样也可以隐式转换为bool型(取值为false)。但是不存在到整形的隐式类型转换。
有了nullptr,可以解决原来C++中NULL的二义性问题;
voidF(int a){ cout<<a<<endl; } voidF(int*p){ assert(p != NULL); cout<< p <<endl; } int main(){ int*p = nullptr; int*q = NULL; bool equal = ( p == q ); // equal的值为true,说明p和q都是空指针 int a = nullptr; // 编译失败,nullptr不能转型为int F(0); // 在C++98中编译失败,有二义性;在C++11中调用F(int) F(nullptr); return 0; } |
区间迭代 range-based for loop
C++11扩展了for的语法,终于支持区间迭代,可以便捷的迭代一个容器的内的元素;
int my_array[5] = {1, 2, 3, 4, 5};
// double the value of each element in my_array:
for (int &x : my_array) {
x *= 2;
}
当然,这时候使用auto会更简单;
for (auto &x : my_array) {
x *= 2;
}
如果有更为复杂的场景,使用auto的优势立刻体现出来:
map<string,int> map;
map.insert<make_pair<>("ss",1);
for(auto &x : my_map)
{
cout << x.first << "/" << x.second;
}