zoukankan      html  css  js  c++  java
  • 数组

    vector 类型相同,数组也是存放类型相同的对象的容器,与 vector 不同的是,数组的大小是确定不变的,不能随意向数组中添加元素。

    定义和初始化内置数组

    数组的维度是编译时已知的,维度必须是一个常量表达式。

    和内置类型一样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值。

    显示初始化数组元素

    • 可以对数组元素进行列表初始化,此时允许忽略数组的维度,如果没有明确指明数组的维度,编译器会根据初始值的数量计算并推测出来。
    • 如果指明了数组的维度,那么初始值的总数量不能超出指定的大小。
    • 如果维度比提供的初始值数量大,则用提供的初始值初始化靠前的元素,剩下的元素被初始化为默认值。
    const unsigned sz = 3;
    int ia1[sz] = { 0,1,2 };	//ia1含有三个元素
    int a2[] = { 0,1,2 };		//a2 是含有三个元素的数组
    int a3[5] = { 0,1,2 };		//a2 是含有5个元素的数组,前三个元素分别是0,1,2,后两个元素默认初始化
    int a4[2] = { 1,2,3 };		//错误,初始值过多
    

    字符数组的特殊性

    字符数组可以使用字符串字面值进行初始化,当使用这种方式时,一定要注意字符串字面值末尾还有一个空字符,这个空字符也会像字符串其它字符一样被拷贝到字符数组中。

    char a1[] = { 'C','+','+' };	//列表初始化,没有空字符
    char a2[] = { 'C','+','+',''};	//列表初始化,含有显示的空字符
    char a3[] = "C++";	//自动添加表示字符串结尾的空字符
    const char a4[6] = "Daniel";	//错误,没有空间容纳空字符
    

    不允许拷贝和赋值

    不能将数组的内容直接拷贝给其它数组作为初始值,也不能用数组为其它数组赋值:

    int a[] = {0,1,2};
    int a2[] = a;	//错误,不允许使用一个数组初始化另一个数组
    a2 = a;	//错误,不能将数组直接赋值给另外一个数组
    

    访问数组元素

    数组元素可以使用范围 for 语句或下标运算符来访问。

    在使用数组下标的时候,通常将其定义为 size_t类型,size_t 是一种与机器无关的无符号类型,它被设计的足够大以便能表示内存中任意对象的大小。size_t 定义在头文件 cstddef 中。

    指针和数组

    数组的元素也是对象,对数组元素使用下标运算符得到该数组指定位置的元素,对数组元素使用取地址符就能得到指向该元素的指针。

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

    数组还有一个特性:很多用到数组名的地方,编译器会自动将其替换成为一个指向数组首元素的指针。

    string *p2 = nums;	//等价于p2 = &nums[0]
    

    使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组。

    使用decltype关键字时,编译器不会将数组以指针看待。

    int ia[] = {0,1,2,3,4,5,6,7,8,9};
    auto ia2(ia);	//ia2是一个整型指针,指向ia的第一个元素
    
    decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};
    

    标准库函数 begin 和 end

    C++11新标准引入的两个函数 beginend。因为类不是类类型,因此这两个函数不是成员函数,正确的使用方法是将数组作为它们的参数。

    int ia[] = {0,1,2,3,4,5,6,7,8,9};
    int *beg = begin(ia);
    int *end end(ia);	//返回数组尾元素下一个位置的指针
    

    指针运算

    指针的基本运算包含:解引用,递增,比较,与整数相加,两个指针相减。

    • 两个指针相减的前提是两个必须指向同一个数组当中的元素,两个指针相减的结果是 ptrdiff_t 的标准类型,它定义在 头文件 <cstddef> 中, ptrdiff_t 是一种带符号类型。、
    • 给指针加上一个整数,得到的新指针仍需指向同一数组的其它元素,或者指向同一数组的尾元素的下一个位置。
    • 只要两个指针指向同一个数组的元素,或者指向该数组的尾元素的下一个位置,就能利用关系运算符对其进行比较。

    下标和指针

    int ia = {0,2,4,6,8};
    
    int i = ia[2];	//ia[2]是(ia+2)所指向的元素
    int *p = ia;	//p指向ia的首元素
    i = *(p+2);		//等价于ia[2]
    
    int *p = &ia[2];	//p指向索引为2的元素
    int j = p[1];		//p[1]等价于*(p+1),就是ia[3]表示的那个元素
    int k = p[-2];		//p[-2]等价于就是ia[0]表示的那个元素
    

    C 风格字符串

    尽管C++支持C风格字符串,但在C++程序中最好不要使用C风格字符串,这是因为C风格字符串不仅使用起来很不方便,而且极易引发程序漏洞,是诸多安全问题的根本原因。

    C 标准库string函数

    C语言标准库提供了一组函数,这些函数可以用于操作C风格字符串,它们定义在 <cstring> 中。

    传入此类函数的指针必须是指向以空字符结束的字符数组。

    混用string对象和C风格字符串

    任何出现字面值的地方都可以用以空字符结束的字符数组来替代:

    • 允许使用以空字符结束的字符数组来初始化 string 对象或为 string 对象赋值。
    • string 对象的加法运算中,允许使用以空字符结尾的字符数组作为其中一个运算对象。

    但是如果程序中需要使用一个C风格字符串,不能直接使用 string 对象来代替它。

    不能用string对象直接初始化指向字符的指针,为了完成这个功能,string 提供了 c_str 的成员函数,c_str函数的返回值是一个C风格字符串,结果指针的类型是 const char*

    使用数组初始化vector

    不允许使用一个数组为另一个内置类型的数组赋值。不允许使用vector对象初始化数组,但是可以使用数组来初始化vector对象。要实现这一目的,只需指明要拷贝区域的首元素地址和尾元素地址。

    int int_arr[] = {0,1,2,3,4,5};
    vector<int> ivec(begin(int_arr),end(int_arr));
    vector<int> subVec(int_arr + 1,int_arr + 4);	//也可以只用数组的一部分初始化vector
    

    注意:

    现代C++程序应该尽量使用 vector 和迭代器,避免使用内置数组和指针;应该尽量使用 string ,避免使用C风格字符串。

  • 相关阅读:
    设计模式复习【1】- 设计原则
    Java8的学习笔记
    Gson关于抽象类的序列化与反序列化
    关于一个Java web与JFrame的深度结合
    《重构》笔记
    JAVA8 Stream API总结的好的文章 —— 持续更
    Spring Boot引入Thymeleaf前端框架的诸多问题
    敏捷开发:原则,模式与实践——第8章 单一职责原则SRP
    maven 你应该懂得那些事
    redis之单机和主从环境搭建
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12498476.html
Copyright © 2011-2022 走看看