覃谈谭的blog


Just for me

vim插件之属性目录NERDTree

0 条评论 vim 无标签 adtxl

转载自https://www.cnblogs.com/littlewrong/p/6535728.html

1、下载安装

下载地址:

官网:http://www.vim.org/scripts/script.php?script_id=1658
GitHib:https://github.com/scrooloose/nerdtree
下载并解压后,把plugin/NERD_tree.vim 和doc/NERD_tree.txt分别拷贝到~/.vim/plugin 和 ~/.vim/doc 目录。

2、基本使用

【命令】

在linux命令行界面,输入vim;输入:NERDTree ,回车。

【配置】

在".vimrc"文件中增加下面配置代码:

" 设置NerdTree

map <F3> :NERDTreeMirror<CR>

map <F3> :NERDTreeToggle<CR>

按F3即可显示或隐藏NerdTree区域了。

3、常用命令

进入当前目录的树形界面,通过小键盘"上下"键,能移动选中的目录或文件。目录前面有"+"号,按Enter会展开目录,文件前面是"-"号,按Enter会在右侧窗口展现该文件的内容,并光标的焦点focus右侧。"ctr+w+h"光标focus左侧树形目录,"ctrl+w+l"光标focus右侧文件显示窗口。多次按"ctrl+w",光标自动在左右侧窗口切换。光标focus左侧树形窗口,按"?"弹出NERDTree的帮助,再次按"?"关闭帮助显示。输入":q"回车,关闭光标所在窗口。

NERDTree提供了丰富的键盘操作方式来浏览和打开文件,介绍一些常用的快捷键:

  • 和编辑文件一样,通过h j k l移动光标定位
  • 打开关闭文件或者目录,如果是文件的话,光标出现在打开的文件中
  • go 效果同上,不过光标保持在文件目录里,类似预览文件内容的功能
  • i和s可以水平分割或纵向分割窗口打开文件,前面加g类似go的功能
  • t 在标签页中打开
  • T 在后台标签页中打开
  • p 到上层目录
  • P 到根目录
  • K 到同目录第一个节点
  • J 到同目录最后一个节点
  • m 显示文件系统菜单(添加、删除、移动操作)
  • ? 帮助
  • q 关闭

CPP基础--表达式之类型转换

0 条评论 C++ 无标签 adtxl

类型转换

何时发生隐式类型转换
在下面这些情况下,编译器会自动地转换运算对象的类型:

  • 在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型。
  • 在条件中,非布尔值转换成布尔类型
  • 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型
  • 如果算术运算关系或关系运算的运算对象有多种类型,则需要转换成同一种类型。
  • 函数调用时也会发生类型转换

1. 算术转换

算术转换的含义是把一种算术类型转换成另外一种算术类型。

2. 其他隐式类型转换

数组转换成指针
在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针:

int ia[10];     // 含有10个整数的数组
int* ip = ia;   // ia转换成指向数组首元素的指针

当数组被用作decltype关键字的参数,或者作为取地址符(&)、sizeof及typeid等运算符的运算对象时,上述转换不会发生。同样的,如果用一个引用来初始化数组,上述转换也不会发生。

指针的转换
C++还规定了其他的指针转换方式,包括常量整数值0或者字面值nullptr能转换成任意指针类型;指向任意非常量的指针能转换成void*;指向任意对象的指针能转换成const void*。

转换成布尔类型
存在一种从算术类型或指针类型向布尔类型自动转换的机制。如果指针或算术类型的值为0,转换结果是false;否则转换结果是true

转换成常量
允许将指向非常量类型的指针转换成指向相应的常量类型的指针,对于引用也是这样。

3. 显式转换

有时我们希望显式地将对象强制转换成另外一种类型。例如,如果想在下面的代码中执行浮点数除法;

int i, j;
double slope = i/j;

就要使用某种方法将i或j显式地转换成double,这种方法称作强制类型转换(cast)。
注:虽然有时不得不使用强制类型转换,但这种方法本质上是非常危险的。

  • 命名的强制类型转换

一个命名的强制类型转换具有如下形式:

cast-name<type>(expression);

其中,type是转换的目标类型,而expression是要转换的值。如果type是引用类型,则结果是左值。
cast-name是static_castdynamic_castconst_castreinterpret_cast中的一种。cast-name指定了执行的是哪种转换。

static_cast

任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast。

// 进行强制类型转换以便执行浮点数除法
double slope = static_cast<double>(j) / i;

static_cast对于编译器无法自动执行的类型转换也非常有用。例如,我么可以使用static_cast找回存在于void*指针中的值:

void* p = &d;       // 正确:任何非常量对象的地址都能存入void*
// 将void*转换回初始的指针类型
double *dp = static_cast<double*>(p);

const_cast

const_cast只能改变运算对象的底层const

const char *pc;
char *p = const_cast<char*>(pc);    //正确,但是通过p写值是未定义的行为

对于将常量对象转换成非常量对象的行为,我们一般称其为“去掉const性质”。一旦我们去掉了某个对象的const性质,编译器就不能再阻止我们对该对象进行写操作了。如果对象本身不再是一个常量,使用强制类型转换获得写权限是合法的行为。然而如果对象是一个常量,再使用const_cast执行写操作就会产生未定义的后果。
只有const_cast能改变表达式的常量属性,同样,const_cast不能用来改变表达式的类型。
const_cast常常用于有函数重载的上下文中。

reinterpret_cast

reinterpret_cast通常为运算对象的位模式提供较低层次上的重新解释。
建议:避免强制类型转换,尤其是reinterpret_cast


CPP基础--迭代器介绍

0 条评论 C++ 无标签 adtxl

迭代器介绍

可以使用下标运算符来访问string对象的字符或vector对象的元素,还有另外一种更通用的机制也可以实现同样的目的,这就是迭代器(iterator)。
类似于指针类型,迭代器也提供了对对象的间接访问。就迭代器而言,其对象是容器中的元素或者string对象中的字符。使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另外一个元素。

1. 使用迭代器

和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员。比如,这些类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素(或第一个字符)的迭代器。如有下述语句:

// b表示v的第一个元素,e表示v尾元素的下一位置
auto b = v.begin(), e = v.end();    // b和e的类型相同

end成员则负责返回指向容器(或string对象)“尾元素的下一位置”的迭代器,也就是说,该迭代器指示的是容器的一个本不存在的“尾后”元素。这个迭代器没什么实际含义,仅是个标记而已,表示我们已经处理完了容器中的所有元素。end成员返回的迭代器常被称作尾后迭代器。
如果容器为空,则begin和end返回的都是同一个迭代器,都是尾后迭代器。

  • 迭代器运算符

imageb765df33f9cb4649.png

和指针类似,也能通过解引用迭代器来获取它所指示的元素,执行解引用的迭代器必须合法并确实指示着某个元素。试图解引用一个非法迭代器或者尾后迭代器都是未被定义的行为。

string s("some string");
if (s.begin() != s.end()) {     // 确保s非空
    auto it = s.begin();        // it表示s的第一个字符
    *it = toupper(*it);         // 将当前字符改写成大写形式
}
  • 将迭代器从一个元素移动到另外一个元素

迭代器使用递增(++)运算符来从一个元素移动到下一个元素。
因为end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用的操作。

  • 迭代器类型

就像不知道string和vector的size_type成员到底是什么类型,一般来说我们也不知道(其实是无须知道)迭代器的精确类型。而实际上,那些拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代器的类型:

vector<int>::iterator it;           // it能读写vector<int>的元素
string::iterator it2;               // it2能读写string对象中的字符

vector<int>::const_iterator it3;    // it3只能读元素,不能写元素
string::const_iterator it4;         // it4只能读字符,不能写字符
  • begin和end运算符

begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator;如果对象不是常量,返回iterator
为了便于专门得到const_iterator类型的返回值,C++11新标准引入了两个新函数,分别是cbegin和cend.不论vector对象本身是否是常量,返回值都是const_iterator。

  • 结合解引用和成员访问操作

解引用迭代器可获得迭代器所指的对象,如果该对象的类型恰好是类,就有可能希望进一步访问它的成员。
例如,对于一个由字符串组成的vector对象来说,要想检查其元素是否为空,令it是该vector对象的迭代器,只需检查it所指字符串是否为空就可以了,其代码如下,

(*it).empty()

为了简化上述表达式,C++定义了箭头运算符(->)。箭头运算符把解引用和成员访问两个操作结合在一起,也就是说,it->mem(*item).mem表达的意思相同

  • 某些对vector对象的操作会使迭代器失效

虽然vector对象可以动态地增长,但是也会有一些副作用。已知的一个限制是不能在范围for循环中向vector对象添加元素。另外一个限制是任何一种可能改变vector对象容量的操作,比如push_back,都会使该vector对象的迭代器失效。
谨记,但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。

2. 迭代器运算

string和vector迭代器提供了更多额外的运算符,一方面可使得迭代器每次移动跨过多个元素,另外也支持迭代器进行关系运算。所有这些运算被称作迭代器运算

image3b0c2483513ef780.png

所谓两个迭代器之间的距离指的是右侧的迭代器向前移动多少位置就能追上左侧的迭代器,其类型是名为difference_type的带符号整型数。


CPP基础--变量和基本类型之处理类型

0 条评论 C++ 无标签 adtxl

处理类型

1. 类型别名

类型别名(type alias)是一个名字,它是某种类型的同义词。使用类型别名还有很多好处,它让复杂的类型名字变得简单明了、易于理解和使用,还有助于清楚地知道使用该类型的真实目的。

  • typedef
typedef double wages;       // wages是double的同义词
typedef wages base, *p;     // base是double的同义词,p是double*的同义词
  • using
    C++11标准规定了一种新的方法,使用别名声明(alias declaration)来定义类型的别名
    using SI = Sales-iteml // SI是Sales_item的同义词

  • 指针、常量和类型别名

如果某个类型别名指代的是复合类型和常量,那么把它用到声明语句里就会产生意向不到的后果

typedef char *pstring;
const pstring cstr = 0;     // cstr是一个指向char的常量指针
const pstring *ps;          // ps是一个指针,它的对象是指向char的常量指针

const是对给定类型的修饰,此时pstring实际上是一个指向char的指针,因此,const pstring就是指向char的常量指针,而非指向常量字符的指针。
遇到一条使用了类型别名的声明语句时,人们往往会错误地尝试把类型别名替换成它本来的样子,以理解该语句的含义:

const char *cstr = 0;   // 是对const pstring cstr的**错误理解**

声明语句中用到了pstring时,其基本数据类型是指针。可是用char*重写了声明语句后,数据类型就变成了char,*成为了声明符的一部分。这样改写的结果是,const char成了基本数据类型。

2. auto类型说明符

auto类型说明符,可以让编译器替我们去分析表达式所属的类型。
使用auto也能在一条语句中声明多个变量。因为一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样:

auto i = 0, *p = &i;        // 正确:i是整数、p是整型指针
auto sz = 0, pi = 3.14;     // 错误:sz和pi的类型不一致
  • 复合类型、常量和auto

编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。
其次,auto一般会忽略掉顶层const,同时底层const则会保留下来,比如当初始值是一个指向常量的指针时:

int i = 0, &r = i;
auto a = r;
const int ci = i, &cr = ci;
auto b = ci;    // b是一个整数(ci的顶层const特性被忽略掉了)
auto c = cr;    // c是一个整数
auto d = &i;    // d是一个整型指针
auto e = &ci;   // e是一个指向整数常量的指针(对常量对象取地址是一种底层const)

如果希望推断出的auto类型是一个顶层const,则需要明确指出:

const auto f = ci;      // ci的推演类型是int,f是const int

3. decltype类型指示符

有时会遇到这种情况:希望从表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量。
decltype,它的作用是选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值