《c++ primer》第四章--数组和指针
来源:互联网 发布:库班和诺维斯基 知乎 编辑:程序博客网 时间:2024/06/05 10:38
数组是c++中类似于标准库vector类型的内置数据结构,与vector相似,数组也是一种存储单一类型对象的容器,其中每个对象没有单独的名字,而是通过它在数组中的位置对它进行访问。
与vector类型相比,数组的显著缺陷在于:数组的长度是固定的,而且程序员无法知道一个指定数组的长度。数组没有获得其容量大小的size操作,也不提供push_back操作在其中自动添加元素。如果需要更改数组的长度,程序员只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组空间中去。~~~~(>_<)~~~~太费劲了...
在现在c++中,更多的使用vector容器来取代数组,数组被严格限制与程序内部使用,只有当性能测试表明使用vector无法达到必要的速度要求时,才使用数组。(看来vector容器虽然用起来很方便,但是速度上不太行啊~~)。
&4.1.1
关于数组的定义和初始化:
数组的维数必须用大于等于一的常量表达式定义,此常量表达式只能包含整形字面值常量、枚举常量或者用常量表达式初始化的整型const对象。非const变量以及要到运行阶段才知道其值的const变量都不能用于定义数组的维数。 ————注意,是数组的维数,不是数组中某个 元素的值~~
例子:
// both buf_size and max_files are const
const unsigned buf_size = 512,max_files = 20 ;
int staff_size = 27; nonconst
const unsigned sz = get_size() ; //const value not known until run time
char input_buffer [ buf _ size ] ; //ok:const variable
string fileTable [max_size +1 ]; // OK:const expression
double salaries [staff_size]; //error: non const variable
int test_scores [ get_size ]; //error: non const expression
int vals [ sz ]; //error: size not known until run time
首先,虽然staff_size是用的字面值常量进行初始化,但是staff_size本身是一个——————非const对象,所以只有在运行时才能获得它的值————————。
因此,使用该变量来定义数组维数是非法的。而对于sz,尽管它是一个const对象,但是它的值要等到运行时调用get_size函数后才知道,因此,它也不能用于定义数组维数。另一方面,由于 max_files 是const 变量,因此表达式
max_size+1
是常量表达式,编译时即可计算出该表达式的值为21。
1.
显示初始化数组元素:
在定义数组是,可为其元素提供一组用逗号分隔的初值,这些初值用 { } 括起来,称为初始化列表:
const unsigned array_size=3;
int ia [ array _ size ] = { 0 , 1, 2 } ;
ps:
如果没有显示提供元素初值,则数组元素会像普通变量一样初始化:
※在函数体外定义的内置数组,其元素均初始化为0;
※在函数体内定义的内置数组,其元素无初始化;
※不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类没有默认构造函数,则必须为该数组的元素提供显示初始化。
※※ 除非显式地提供元素初值,否则内置类型的局部数组元素没有初始化。此时,除了给元素赋值外,其他使用这些元素的操作无意义。 ※※
显式初始化的数组不需要提供指定数组的维数,编译器会根据列出的元素个数类确定数组的长度。
EG:
int a [ ] = { 0 , 1 , 2 } ;
如果初始化列表中维数小于列出的元素个数,那么会怎么样呢?
EG:
int ia [ 3 ] = { 0 , 1 , 2 , 3 , 4 , }; //error: 当家应该能猜到这个错误是什么。。。初始值设定太多(⊙﹏⊙)b
※ 2
特殊的字符数组:
字符数组既可以用一组由花括号括起来、用逗号隔开的字符字面值进行初始化,也可以用一个字符串字面值进行初始化。然而,要注意的是两种初始化方式并不完全是相同,字符串字面值包含一个额外的空字符(NULL) 用于结束字符串。当使用字符串字面值来创建新数组时,将在新数组中加入空字符。
char ca [ ] = { " C++" } ;
ca有四个元素,c,+,+,‘\0’
※ 注意:
与vector不同的是,一个数组不能用另一个数组进行初始化,也不能将一个数组赋值给另一个数组,这些操作都是违法的~~!违法!
※4.1.2
数组的操作:
和vector操作一样,数组元素可以用下表操作符来访问,数组元素也是从0开始计数。
在这里要注意一点,在c++中,vector使用vector::size_type作为下表类型,而数组下标的正确类型则是size_t(也就是说,用int)也是可以的)~~~
i例如:
int main()
{
const size_t a_size = 5;
const int a_s = 6;
int ia[a_size];
int iaa[a_s];
}
这两种方式都是可以的,但是在编程序时千万别忘了int a_s前面的const,如果忘了就去上面看一下。
ps:
在我们使用数组的时候,千万要对数组下标进行检查,以防 “ 过界 ”,导致安全问题的最常见原因是所谓 “ 缓冲区溢出 ”,就是因为在编程时没有检查下标,这种错误常常会让人忽略,但确实是不容轻视的一个错误。
※4.2
指针的引入:
首先,指针的概念很简单:用于指向对象。和迭代器一样,指针提供对其所指对象的间接访问,只不过是指针结构更通用一些。当然,和迭代器不同的是,指针指向单个对象,而迭代器只能用于访问容器内的元素。
*****************具体来说,指针保存另一个对象的地址~
※4.2.2
指针的定义:
c++中使用*符号把一个标识符声明为指针:
vector < int > *pvec;
int *p1;
string *ps;
在c++中 也可以使用这种风格声明指针:
string* ps;
ps也是指向string对象的一个指针。
PS:
不过在,上面的第二种声明指针的风格很容易让人误解,而且在下面这个语句中:
string* ps1,ps2;
只有ps1是一个string * 类型,而ps2只是一个普通的string类型的对象~~!
4
指针可能的取值:
一个有效指针必然是一下三种状态之一:
( 1 ): 保存一个特定对象的地址;
( 2 ): 指向某个对象后面的另一个对象;
( 3 ) : 0值。
5:
我们应该尽量避免使用未初始化的指针,虽然指针可以不声明时马上定义,但是就像使用其他没有初始化的变量一样,在使用它的时候几乎总会导致运行时崩溃。然而,导致崩溃的这一原因很难发现。
对大多数编译器来说,如果使用未初始化的指针,会将指针中存放的不确定值视为地址,然后操纵该内存地址中存放的位内容。
6
指针初始化和赋值操作的约束:
对指针进行以上操作只能使用一下四种类型的值:
1: 0值常量表达式
2: 类型匹配的对象的地址。
3: 另一个对象之后的下一个地址。
4: 同类型领一个有效指针。
7
特殊类型的指针:void*指针
它可以保存任何类型对象的地址~
当然,不允许使用void*类型的指针操纵它所指向的对象。
※4.2.3
指针操作
指针提供间接操纵其所指对象的功能,与对迭代器进行解引用一样,对指针进行解引用可以访问它所指的对象,* 操作符将获取指针所指的对象。
string s ( " hello world " ) ;
string * SP = & s ;
cout << * sp; // prints hello world;
如果给你一个指针,要将指针所指的对象进行修改,可以怎样做呢?
* SP = “ good bye ” ;
这样指针所指的对象就改成了 “ good bye ” ,也没啥难度是吧。。。
※ 注意给指针赋值或通过指针进行赋值:
对于初学的人来说,如何区分是给指针赋值还是通过指针进行赋值确实是挺困难的,不过我们可以记住一个重要的方法: 如果对左操作符进行了解引,那么就是修改指针所指对象的值,如果没有使用解引用,那么就是修改指针本身。
考虑下面这个例子:
string s1 ( " some value " ) ;
string *sp1=&s1;
string s2 ( " another " ) ;
string *sp2=&s2;
*sp1=" a new value " ;
// 这里修改了s1的值。
sp1= sp2;
// 这里修改了sp1的指针,使其和sp2指向相同的对象。
※在这里顺便进行一下指针和引用的比较
虽然两者都可以间接访问另一个值,但是它们有两个重要的区别:
1: 定义引用时没有初始化是错误的;
2: 给引用赋值修改的是该引用所关联的对象,因为它是对象的别名,。
4.3 c风格字符串
2.2节中我们已经用过了字符串字面值,并了解了字符串的类型就是字符串常量的数组,现在可以更明确地认识到:它是一个 const char类型的数组,c++从c语言继承下来的一种通用结构是 c风格字符串,而字符串字面值就是这种类型的实例,然而,c风格字符串既不能确切的归结为c的类型,也不能归结为c++,它是以空字符NULL结束的字符数组。
- 《C++Primer》 第四章 数组和指针
- C++Primer (第四版) 第四章 数组和指针
- C++Primer笔记 第四章 数组和指针
- C++Primer笔记3(第四章-数组和指针)
- C++ Primer 第四章 数组和指针
- 《c++ primer》第四章--数组和指针
- C++ primer 第四章--数组和指针
- C++ Primer 第四章 数组和指针
- C++primer第四版第四章数组与指针
- 【重学《C++Primer第四版》】第四章、数组和指针
- C++ Primer 【第四版】第四章 数组和指针
- C++primer第四章(二):数组和指针——指针
- C++primer第四章(一):数组和指针——数组
- C++primer学习笔记第四章-数组与指针
- C++Primer学习笔记第四章(4/18) 数组和指针
- 【C++ primer 笔记】第四章 数组和指针
- C++ Primer 4 第四章 数组和指针
- C++ Primer学习笔记---第四章 数组和指针
- hdu 1022 Train Problem I
- Unable to locate package错误解决办法
- 五道口-硬件自由日-Xboard.io参会
- Milano Store OpenCart 2.0 主题模板 ABC-0473
- Intel Threading Building Blocks 编程指南 : 内存分配
- 《c++ primer》第四章--数组和指针
- 求100到999之间水仙花的个数
- java 线程池架构
- 第八周项目一 实现复数类中的运算符重载-(1)定义复数类重在运算符+-*/
- Jetty(7.6.16)和VisualVM建立链接
- 带符号8位整型向带符号16位整型的强制转换
- ubuntu 命令行模式和图形界面切换
- 使用Volley 的NetWorkImageView报空指针问题
- Yourkit 监控Jetty(stand-alone)