C++ / Syntax
现代 C++ 语法笔记(四)
整理原始字面量、long long、成员初始化、模板、异常等现代 C++ 语法点。
decltype
decltype:用于得到类型,即declare type
用法:
int a = 9;
decltype(a) b; //b--int
decltype(a+0.1) c; //c--double
decltype(func()) d; //d--func的返回值
当表达式是左值或者带有括号时,推导出的类型会带有const
decltype((1+1)) e; //e--const int
int n = 1;
decltype(n = n + 1) f; //d--const int
基于范围的for循环
不需要传递容器的两端,直接抽取容器中的元素进行遍历,使编码和维护更加简单
语法
for (declaration : expression)
{
//循环体
}
declaration - 遍历声明,被遍历到的元素会被储存到声明的变量中
expression - 遍历的对象(表达式、容器、数组、初始化列表)
实例
vector<int> v = {1, 2, 3};
for(auto value : v)
{
cout << value << " ";
}
需要注意的是,v中的元素是被拷贝到了value中,因此无法对v的元素进行修改
如需修改,需声明为引用 for(auto &value : v)
注意
- 如果想要让变量不允许被修改,那可以使用
const auto &,效率比auto更高
- 在range-base for中,auto推导关联型容器(如map)时得到的类型会是容器中的value_type,相当于一个pair对象,所以提取键值对的方式要用
it.first和it.second,而不是和迭代器一样用->
- 即使使用了引用,像set的元素和关联型容器元素的key值仍然是不能被修改的,这个由容器内部的性质决定
- 冒号后面的表达式只有在开始时会被执行一次,得到遍历对象之后就确定好迭代的范围
- 多用于只需要当前元素的场景,当类似于同时需要操作当前元素和下一个元素这种场景时,一般还是用普通的for
指针空值类型-nullptr
为什么不用NULL
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
在C++中NULL就是0,因为不像在C里面void *可以隐式转换为其它指针类型
NULL和0无法区分带来了一些弊端,比如函数重载时:
void func(char* p);
void func(int n);
func(NULL) //此时第二个函数会被调用,不符合要求
nullptr
C++11引入的关键字,用于初始化空指针类型,任何指针类型都可以用它来初始化,也可以隐式转换为各种指针类型
要注意的是,nullptr不能转换为整型,它的类型是 std::nullptr_t
但下列场景是正确的
char* p = nullptr;
//1.
if (p == 0); //正确,此处是0转换为了空指针
//2.
if (!p); //正确,此处转换成的是bool类型