Back to VNotes

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.firstit.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类型