1

C++ 学习笔记

 2 years ago
source link: https://cndaqiang.github.io/2021/03/30/cpp-learn/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C++ 学习笔记

虽然整理成博客,很浪费时间,不过,每次忘记后,再捡起来,还要好久,还是继续把笔记整理成文章
该文不完全,遇到其他的语法再添进来

C++中文版【王刚 杨】

  • 分号;表示语句结束,必不可少
  • 注释 - 单行注释 //开头 - 继承自C语言/**/之间,单行或多行,不能嵌套
  • 缩进自由,{可以放在函数/while/…等的同行也可以下一行
  • 大小写敏感
  • 变量名一般用小写字母, 用户自定义的类一般大写字母开头, 多个单词组成的,单词首字母大写或下划线隔开
  • 变量在用之前定义/声明就可以,不用像Fortran一样在开头定义
  • 使用标准库中的命令空间中的对象,使用域操作符::,如std::cin
    可以使用using std::cin,之后就可以直接使用cin替换std::cin
  • 引入了#include<iostream>后, 这两个标准库#include<string> #include<cctype>没引入也可以使用相应std中的变量
  • 语句以;结束,可以用空语句. 多加;的问题: while( condition) ;表示循环体是空的
  • 语句块用{}括起来,{}外面不加;,空块{}也表示空语句
  • 在if的{}定义的变量、引用等操作,在{}外无效

头文件通常包含哪些只能被定义一次的实体,如类、const、constexpr变量等.
头文件一旦改变,相关源文件必须重新编译以获得更新过的说明

  • 头文件不建议包含using声明,可能会和代码中的变量冲突
  • C++标准库也兼容来C语言的辨准库,C语言的头文件如name.h,C++将这些文件命名为cname,即去.hc,如C语言中的ctype.h在C++中就是cctype
    cname中定义的类总能在命名空间std中找到. 而如果使用name.h文件,则需要额外记哪些是从C语言继承的,哪些是C++特有的,一般使用cname的形式

    预处理器preprocessor

    在编译前预处理源码,如#include就会用头文件的内容代替#include

可以使用预处理的功能确保头文件只被引入一次,即头文件保护符功能
整个程序每个头文件的保护符必须唯一,通常以头文件中类的名字来构建保护符的名字,以确保其唯一性,为了避免和程序的其他实体发生名字冲突,一般把预处理变量的名字全部大写.

//没有定义SALES_DATA_H 则包含下面内容; 第二次include时已经定义了就不包含了
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data{
      std::string bookNo;
};
#endif

类型 尺寸 范围 char 1 个字节(1 Byte = 8 bit) -128 到 127 或者 0 到 255 unsigned char 1 个字节 0 到 255 signed char 1 个字节 -128 到 127 wchar_t 2 个字节 1 个宽字符 wchar16_t 2个字节 Unicode 宽字符 wchar32_t 4 个字节 Unicode 宽字符 int 4 个字节 -2147483648 到 2147483647 unsigned int 4 个字节 0 到 4294967295 signed int 4 个字节 -2147483648 到 2147483647 short int 2 个字节 -32768 到 32767 unsigned short int 2 个字节 0 到 65,535 signed short int 2 个字节 -32768 到 32767 long int 8 个字节 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 signed long int 8 个字节 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 unsigned long int 8 个字节 0 到 18,446,744,073,709,551,615 float 4 个字节 精度型占4个字节(32位)内存空间,+/- 3.4e +/- 38 (~7 个数字) double 8 个字节 双精度型占8 个字节(64位)内存空间,+/- 1.7e +/- 308 (~15 个数字) long double 16 个字节 长双精度型 16 个字节(128位)内存空间,可提供18-19位有效数字。 bool true/false  

向对象进行赋值

int i;
i=3.14; // i的值为3
double pi=i; //pi的值为3.0

自面值常量literal

常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。
常量可以是任何的基本数据类型,可分为整型数字、浮点数字、字符、字符串和布尔值。
常量就像是常规的变量,只不过常量的值在定义后不能进行修改。

  • 20 十进制, -42中的-不在字面值内,代表对字面值42取负
    通过后缀指定类型 - 20u,20U unsigned无符号整数 - 20l,20L long长整数 - 20ll,20LL long long整数 - 20ul unsigned long 无符号长整数
  • 024 八进制
  • 0x16 十六进制
    std::cout << 20 <<" "<< 024 <<" " << 0x14 << std::endl;,输出20 20 20
  • 1.234
    后缀指定类型: fF float型, lL longdouble, 示例 1.234f

字符和字符串

  • 'a' 字符字面值
    前缀指定类型:u,U,L,u8分别代表char16_t,char32_t,wchar_t,char
  • "hello world" 字符串字面值,编译器在字符串结尾添加空字符'\0',因此实际长度比内容对1
    'A'"A"的区别是'A'是字符,"A"是字符数组,包含A\0

转义序列 含义 \\ \ 字符 \' ’ 字符 \" ” 字符 \? ? 字符 \a 警报铃声 \b 退格键 \f 换页符 \n 换行符 \r 回车 \t 水平制表符 \v 垂直制表符 \ooo 一到三位的八进制数 \xhh . . . 一个或多个数字的十六进制数

bool型 - true - false

给类型起个别名, 可以用别名替代原类型名进行使用,但是不是简单换为之前的样子

typedef int in1, in2;   // in1,in2  都是int的别名
in1 ji;
in2 j2;
j2=10;
typedef int *p; // p是int*的同义词

c++11可以使用别名声明来定义类型的别名

using SI=Sales_item;

复合类型或常量的别名可能会产生意想不到的后果, 这里不能简单替换

typedef char *pstring; // pstring是指向char的指针
const pstring cstr=0;   //  const pstring是常数指针类型, 等价于const *chat cstr
// 上一条就不能简单替换为const char * 
const pstring *ps; // ps是是个指针,指向“常数指针”
const char * ps2; // 这里的ps2是指针,指向常变量 

auto类型

c++11标准,根据初值(表达式)内容分析所属类型,因此一定有初值

auto  a=i+j; //根据 i+j的类型推断出a的类型

auto会忽略掉顶层const,同时底层const则会保留下来

const int ci=10;  // ci顶层const,常变量
auto e=&ci; // e是底层const,是指向整型常量的指针

auto也可以和引用一起用

auto &g=ci; 
const auto &j=42; // 可以为常量, 指向表达式的常量引用

decltype

c++11标准,很具表达式类型判断类型,单不赋初值

decltype(f()) sum=x; //sum的类型为函数f的返回类型

如果是引用的类型,则必须在定义时给出初值

const int ci=0, &cj=ci;
decltype(ci) y=ci; //   必须给y赋初值

另外decltype((变量名))双层括号的结果永远是引用,而decltype(变量名)只有在变量是引用是才是引用类型

类型说明符 变量名1,变量名2,变量名3=value,...;

如果类型说明符是类,或者其他库中的命名空间也是如此,如

int a;
Sales_item item; //    类
std::string book("abcdefg") // 库类型std::string

初始化的方式

int i = 0;
int i = {0};
int i{0};   // 列表初始化, 需要C++11标准支持,即编译参数为 g++ -std=c++11
int i(0);

c++将声明和定义区分开. 声明使程序了解变量的类型,定义则是创建变量.
变量只能被定义一次,可以多次声明.

extern int i;
//如果用extern的语句又赋来初值,则视为定义,不再是声明
extern int i(3);

引用/别名

为已有变量(对象)起一个新名字,并链接到相应的对象,两个名字都指向同一片内存区域

int i;
int &i2 = i;      // 右边必须是一个对象, 左边的类型要与右边的对象类型一致, 可以理解为新建立个变量叫i2,不分配新内存而是将其内存地址 &i2 设置和i一样
i=10;
std::cout << i2;  //输出10

指针是一种对象,值是指向不同的对象,可以随时更改其值即指向不同的对象,引用只是起一个名字,且只能指向一个对象.
指针的声明用*指针名,声明的类型必须同将来指向的对象的类型名一致

int i;
int *pi = &i;
std::cout << *pi;  //用*返回指针指向的对象的值
std::cout << pi;  //不加*返回指针的内容,即相应对象内存地址,等价于 std::cout << &i
std::cout << &i;  //返回i的地址, 即pi的内容
std::cout << π  //返回pi的地址

解引符号*作用到指针上就等价于指向的对象本身,可以进行赋值等操作,
在声明时*用于定义变量是指针*,指向指针的指针**,指向(指向指针的指针)***
*是运算符, int *pi,int* pi,int * pi是等价的
cndaqiang: *代表该对象的内容, int *p,表明p的内容是个整型,即p是指针,后面调用这个指针的内容也要*p, 也可以理解为int*定义的是整型指针
&提取地址符号

int i;
int *pi = &i;
*pi=100;    // 可以这样修改原始变量空间
std::cout << i;

空指针,不能把整型等类型直接赋值给指针, 空指针if ( pi )条件返回false

pi=NULL
pi=0  //    可以赋值为0,等价于NULL,但不能赋值1,2...以及整型变量
i=0
pi=i // 这是错误的
pi=1 // 这是错误的

void类型的指针,可以指向任意类型的对象,但是他和普通指针不一样,只能用于指针比较、作为函数的输入或输出、或者赋予另一个void型指针. 不能操作void指向的对象, 也不能了解对象的类型

void *vp=&i;
std::cout << vp;
//std::cout << *vp; //错误用法

指向指针的指针,使用多个*进行定义/声明,使用多个*去取出存储的对象

int i;
int *pi = &i;
int **ppi = π
int ***pppi = &ppi;
//可以继续无限套娃
i=10;
std::cout << i << *pi << **ppi << ***pppi ;

对指针进行引用,不是创建新的指针,而是指向想应指针的引用,引用后的使用和被引用的指针相同,就是起个别名而已

int ***&rp=pppi;
std::cout << i << *pi << **ppi << ***pppi << ***rp;

常变量const

const int i=20;

常量的引用类型必须其引用的对象相同.
第一种例外, 初始化常量引用时允许用任意表达式作为初值,只要该表达式的结果可以转换成引用的类型即可,编译器会把计算结果保存到一个临时量对象,然后引用指向此临时量.但是非常量的引用不可以引向表达式

const int i=11;
int i2=10;
const int &ri=i;
const int &ri2=i2; // 表达式可以转换也可以
const int &ri3=34; // 表达式可以转换也可以
int &r4=ri*2; //错误语法, 非const的引用是不可以的

默认的常量只能被本文件访问,在声明和定义时添加extern允许全局访问

extern const int i=256; //定义
extern const int i ; //头文件中进行声明

底层const:对象的内容可以被改变, 即指向常变量的指针也必须加const进行定义

const int *ip;    //底层const,可以改变ip的值, ip指向常变量

顶层const:对象的内容不可以被改变

  • 常指针,指针指向固定的指针
  • 常变量,不能改变值
    int *const pc=&i; // 顶层const, pc指向&i,不可以被改变
    const int c=42;   //顶层const, 常变量
    

引用常变量也要加上const

const int &ri = i;

常量表达式:在编译过程就能得到计算结果的表达式

const int max_kpoint=256;     //    常量表达式
const int limk=max_kpoint+1;  //常量表达式,编译时就可以确定的值是常量表达式
const int sz=get_size();      // 运行时才能得到该常量的具体数值

c++11新标准规定允许将变量声明为constexpr类型,以便有编译器验证变量的值是否是常量表达式.
constexpr支持的类型都是字面值类型,不能是用户自定义的类型.
constexpr声明中如果定义了指针,则仅对指针有效, 即顶层const

const int *ip;    //指向整型常量的指针
constexpr int *ip;    //指向整型的常量指针

数组的大小固定,如果不清楚元素的确切个数,建议使用vector
定义数组时必须指明数组的类型,不允许使用auto关键词根据初始判断类型.
数组的元素应为对象,因此不存在引用的数组. ?应该是元素不可以是引用,但可以被引用
使用a[i]下标访问

int a[10]; //10个元素的整数数组
int *b[10]; //10个元素数组,数组每个元素的类型为整型的指针

定义和初始化

int a[3]={0,1,2};
int b[ ]={0,1,2};// b[3]={0,1,2}
int c[5]={0,1,2}; // 缺省有默认值, a[5]={0,1,2,0,0}
string d[3]={"hi"}; //string也可以
char a[]={'C','+','+'};
char a[]={'C','+','+','\0'}; //包含显示的空字符
char a[]="C++"; //字符数组特殊,可以这样初始化,包含显示的空字符`\0`,此时如果指定a的大小应至少为4
int *pi[10]; //指针数组
int &pr[10]; //错误,元素不能为引用
int a[2][3]={
      {1,2,3},
      {4,5,6}
};
int a[2][3]={1,2,3,4,5,6};

引用数组,指向数组的指针

int arr[10];
int (&arrRef)[10] = arr;
int (*Parray)[10]=&arr;

数组不可以直接拷贝和赋值,数组名一般表示位置a+4则是第5个元素的位置

int a2[]=a; //错误
a2=a;//错误

指针和数组

在很多用到数组名字的地方,编译器会自动替换为指向数组首元素的指针

string nums[]={"one","two","three"};
string *p=&nums[0];
//等价于
string *p=nums;

[略]迭代器

  • i=f1()+f2(),f1f2的执行顺序未知
  • 算术运算符+-*/%加减乘除取余
  • 逻辑<,<=,>,>=,==,!=,&&,||
  • 允许赋值a=b=0,即b=0;a=b
  • 前置计算++i返回加完的i,
    后置计算i++返回加之前的i(这种返回的是运算之前的内容需要额外的存储,除非必要时不建议)
  • 后置递增运算符优先级高于解引用运算符*pbeg++等价于*(pbeg++),可以用于循环提取元素
  • 条件运算符,条件?真返回的表达式:否返回的表达式
    cond?expr_true:expr_false;
    
  • sizeof(type);sizeof expr 不计算表达式具体的值,仅返回对象/表达式结果占用的空间
  • 逗号运算符,,执行左边的计算,执行右边的计算,最后返回左边的值

运算符 操作 示例 & p&q,p和q全为1时返回1,否则返回0   | p&q,p或q至少一个为1时才返回 1   ^ 异或运算, p&q,p和q相同返回1,不同返回0   ~ 取反~q   << 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)   >> 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃  

使用异或运算可以找到特殊数据,如

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素@LC

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int len = nums.size();
        if ( len == 1 ) return nums[0];
        int result = nums[0]^nums[1];
        for ( int i = 2 ; i < len ; i++ )
        {
            result ^=  nums[i];
        }
    }
};

while

while (condition)
      statement;
while (condition)
{
      statement1;
      ...;
      statement2;
}

读入不确定数量

      int i,sumi;
      sumi=0;
      while(std::cin >> i)
      {
          sumi=sumi+i;
      }
      std::cout << "Input sum is:" << sumi <<std::endl;

do while

do
      expr;
while(condition);
for ( int val=1; val <= 10; ++val)
{
      statement;
}

先判断条件,再执行第一次循环,即初始设置不符合条件也不会执行

int n=10;
//这里的 i < n 是每一次循环后根据新的n重新判断的
for ( int i = 1; i< n; ++i)
{
      statement;
      n=n-1
}
if (condition) {
      statement;
}
else {

}

switch

switch (var) {
      case value1:
            expr;
            expr;
            break;
      case value2:
            expr;
            expr;
            break;
      case ...
      default: /* 可省略,默认情况*/
            expr;
            break
}

如果不加break,则可以在随后一个条件后加break以及统计语句,实现多种情况的统计

  • break终止循环while,do while,for,switch
  • continue,进入下一个循环,适用于跳到while,do while, for的下一个循环
  • goto跳转到同一函数内的另一条语句
    goto label;
    label: expr;
    
  • return可以直接跳出整个函数体的执行,即使套了再多层的循环也会终止

throw略

  • 参数之间逗号隔开,就算类型相同也要隔开int fun(int a, int b)
  • 函数最外层作用域中的局域变量不能使用与函数形参一样的名字?
  • 函数内定义的对象尽在函数的作用域内可见
  • 仅在第一次定义初始化,后续处理的值保留,就是Fortran的SAVE属性,用static定义
  • 调用之前要声明,可以多次声明,可以写在头文件中,函数体和调用可以不在同一个文件,可以分开编译
  • 传递对象名时,是传值调用,形参和实惨相互独立
  • 传递的内容是指针时,修改了指针指向的内存区域,可以实现更改函数外的对象
  • 因为数组不能被拷贝,所以传递的通常是数组的地址(即以指针的方式进行传递)
  • main的参数
    int main(int argc, char *argv[]) { ... }
    

    argv[0-...],

  • 默认参数,可以调用时可以省略实参
    typedef string::size_type sz;
    string screen( sz ht=24, sz wid = 80, char backgrnd = ' ' )
    

同一作用域内几个函数名字相同单参数不同时,称为函数重载, 就和Fortran的interface的同名函数重构功能

注意结束定义处的分号

struct 类名
{
      类体
};    // 此处分号不可缺少

也可以通过class创建

class 类名
{
      类体
};    // 此处分号不可缺少

struc和class的区别在于:对于structure在定义似一个访问说明符之前的成员是public的,而class是private的. 如果希望成员都是public时使用structure,希望成员时private使用class

类名 对象(变量)名;
对象.对象

iostream

c++为定义任何的输入输出(IO)语句,使用标准库来实现. 标准库的4个IO对象.

  • std::cin 标准输入,istream类型的对象
  • std::cout 标准输出,ostream类型的对象
  • std::cerr 标准错误,
  • std::clog 一般信息,

输入和输出以流的方式进行,比如std::cout << "Input num is:" << i <<std::endl;,就是把 "Input num is:",i,std::endl依次流向标准输出.

输出运算符<<左侧是ostream类型的对象(如std::cout),右侧是对象要打印的值,运算的返回值是左侧的对象,因此std::cout << A << B;等价于(std::cout << A) << B;,以及std::cout << A; std::cout << B;

输入运算符>>同理返回左侧的对象, std::cin >> A >> B;等价于(std::cin >> A) >> B;,以及std::cin >> A; std::cin >> B;

std::cin >> A 读入结束或者读入数据和A的类型冲突时,返回False,可以配合while,if等进行联合使用,读入不定数量的输入/对读入进行判断, Unix系统的文件结束输入为ctrl+d(输入完成,先回车在ctrl+d)

std::endl功能一是结束本行,可以用”\n”达到换行的功能, std:endl还有将内存缓冲区的内容刷到设备的作用. 类似于fortran中的flush(6), 便于找到bug的地方.

这些对象都来自std的命令空间namespace, 因此在使用的时候要用作用域算符::调用

#include<iostream>
int main()
{
      std::cout << "hello world" << std::endl;
      std::cout << "Input:" ;
      int i;
      std::cin >> i;
      std::cout << "Input num is:" << i <<std::endl;
      return 0;
}

string

因为某些历史原因,也为了与C兼容,所以C++语言中的字符串字面值char类型并不是标准库类型string的对象.切记, 字符串字面值与string是不同的类型

#include <string>
using std::string;
main()
{
      return 0;
}

定义和初始化

string是一个类,初始化这个类的对象, 通过()进行(操作计算出来的)直接初始化,使用=进行拷贝初始化

string s1; //默认初始化,s1是一个空串
string s2(s1); // s2是s1的副本,
string s3("hello"); //s3是hello的副本
string s2=s1; //  同上
string s3="hello"; //同上
string s4(n,'c'); //s4由n个'c'组成的串

操作 含有 os<<s 将s写到输出流os当中,返回os, 即std::cout << si << sj; is>>s输入流is中读取字符串赋给s,字符串以空白分隔,返回is, 即std::cin >> si >> sj; getline(is,s) getline就是从输入流is中读取一行(到换行符位置)赋给s(不包括换行符)
读到末尾时会返回False,其他情况返回true
>>是等价的,也可以和while连用 s.empty() s为空返回true,否则返回 false s.size() 返回s中字符的个数 s[n] 返回s中第n个字符的引用,位置n从0计起,string和vector的下标只能用于访问,不能修改 s1+s2 返回s1和s2连接后的结果 s1=s2 用s2的副本代替s1中原来的字符 s1==s2
s1!=s2 如果s1和s2中所含的字符完全一样,则它们相等;
string对象的相等性判断对字母的大小写敏感 <,<=,>,>= 利用字符在字典中的顺序进行比较,且对字母的大小写敏感

C++11支持使用for处理string对象的每个字符,配合ispinct()等函数可以进行统计

      string s="hello123";
      for ( auto tmp : s)
            std::cout << tmp << "\n";

也可以用for改变

      string s="hello123";
      for ( auto &tmp : s) // 这里tmp是引用,指向了相应位置的地址
            tmp=toupper(tmp);

vector

  • C++标准要求vectory能在运行时高效添加元素,因此和其他语言的定义时指明具体容量以加速计算相反,通常先建立空的vector,后期动态添加
    #include<vector>
    using std::vector;
    

    vector是类模版,(类、函数)模版不是类,而是为生成类或函数便携的一份声明,
    vector为例,提供的信息供编译器创建类(实例化).这里其实是创建各种类型的组成个一个的类.

    vector<int> ivec; \\生成一个int元素组成的类,并创建相应的对象ivec
    vector<vector<string>> ivec;  \\向量元素是vectory对象
    

列表初始化是C++11的特性.
注意{}()的区别

v2.push_back(i);   //加到末尾
//插入到第一个元素前面
v2.insert(v2.begin(),8);//在最前面插入新元素8。 
v2.insert(v2.begin(),3,8);//在最前面插入新元素{8,8,8}。 
//由于v.end() == v.begin()+v.size()
v2.insert(v2.end(),8);//在末尾插入新元素8。 
//赋值v[0-3](不包括v.begin()+4),到b[4-]
//复制到第k个(下标是k-1),v.begin()+k
copy(v.begin(),v.begin()+4,b.begin()+4);

v.begin()+v.size()等价于v.end(),完整复制即copy(v.begin(),v.end(),b.bengin())

#include <algorithm>
std::sort (v.begin(), v.end());

C++ STL vector删除元素的几种方式(超级详细)

//删除第j个元素
auto iter = nums.erase(nums.begin()+j-1);
//删除num[j]
auto iter = nums.erase(nums.begin()+j);

使用引用和传递地址的方式可以改变vectory的值, 传值调用无法改变原先的值

// 传值
int fun1( vector<int> a)
{
std::cout << "fun1" ;
 for ( int i=0; i<a.size(); i++)
{
        std::cout << a[i];
}
std::cout << std::endl;

return 0;
}

// 引用传入
int fun2( vector<int>& a)
{
std::cout << "fun1" ;
 for ( int i=0; i<a.size(); i++)
{
        std::cout << a[i];
        a[i]=199;
}
std::cout << std::endl;

return 0;
}
int main()
{
std::cout << "hi" <<std::endl;

vector<int> v={0,1,2,3,4,5,6,7,8,9,10};
int j;
j=fun1(v);
//引用传入才可以改变值
j=fun2(v);
std::cout << v[0] << std::endl;

C++map用法@W3Cschool
类似字典,使用关键词进行索引,关键词可以是多种类型

#include <map>
std::map<关键词类型,值类型> 变量名;
//如
std::map<int,int> mymap;
std::map < int , std::string > mapPerson;
mapPerson.insert(pair < int,string > (1,"Jim"));
mapPerson.insert(std::map < int, std::string > ::value_type (2, "Tom"));
mapPerson[3] = "Jerry";
  • begin() 返回指向 map 头部的迭代器
  • clear() 删除所有元素
  • begin() 返回指向 map 头部的迭代器
  • clear() 删除所有元素
  • count() 返回指定元素出现的次数,返回整数, 只能是0或1
  • empty() 如果 map 为空则返回 true
  • end() 返回指向 map 末尾的迭代器
  • equal_range() 返回特殊条目的迭代器对
  • erase() 删除一个元素
  • find() 查找一个元素
  • get_allocator() 返回map的配置器
  • insert() 插入元素
  • key_comp() 返回比较元素key的函数
  • lower_bound() 返回键值>=给定元素的第一个位置
  • max_size() 返回可以容纳的最大元素个数
  • rbegin() 返回一个指向map尾部的逆向迭代器
  • rend() 返回一个指向map头部的逆向迭代器
  • size() 返回map中元素的个数
  • swap() 交换两个map
  • upper_bound() 返回键值>给定元素的第一个位置
  • value_comp() 返回比较元素value的函数

[略]迭代器

#include<set>
        int len = nums.size();
        if ( len == 1 ) return false;
//        set虽然可行但不快
        set<int> set_nums;
        for ( int i = 0; i < len  ; i++)
        {
          //插入新元素, 并判断是否存在
          pair<set<int>::iterator,bool>  pair1=set_nums.insert(nums[i]);
          if ( pair1.second == false ) return true;
        }     

本文首发于我的博客@cndaqiang.
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK