现代C++程序应尽量使用vector和迭代器类型,而避免使用低级的数组和指针。
设计良好的程序只有在强调速度时才在类实现的内部实现数组和指针。
更多地使用vector来取代数组,数组被严格限制于程序内部使用。
int staff = 27只有在运行时才能获得它的值
char ca1[] = {'C', '+' , '+'}; // no null 维数3
char ca2[] = {'C' , '+' , ' + ', ' '} // explicit null 维数4
char ca3[] = "C++" 维数四 // null terminator added automatically
不允许数组直接复制和赋值
数组下标的正确类型是size_t
vector的遍历可使用下标或迭代器实现,同理,
也可用下标或指针(pointer)来遍历数组。
指针是指向某种类型对象的复合数据类型,是用于数组的迭代器:指向数组中的一个元素。
指针用于指向对象。
与迭代器一样,指针提供对其所指对象的间接访问,只是指针结构更通用一些。
与迭代器不同的是,指针用于指向单个对象,而迭代器只能用于访问容器内的元素。
指针保存的是另一个对象的地址
&取地址(address-of)操作符
2.3.1左值:左值可以出现在赋值语句的左边或右边
右值:右值只能出现在赋值的右边,不能出现在赋值语句的左边
有效的指针
1.保存一个特定对象的地址
2.指向某个对象后面的另一个对象
3.0值。若指针保存0值,表明它不指向任何对象。
很多运行时错误都源于使用了未初始化的指针
建议程序员在使用之前初始化所有的变量,尤其是指针。
C++把指针初始化为NULL等效于(==)初始化为0值 C
把int型变量赋给指针是非法的,尽管此int型变量的值可能为0
void*指针 可以保存任何类型对象的地址
指针提供间接操纵其所指对象的功能。与迭代器进行解引用操作一样。
对指针进行解引用课访问它所指的对象,*操作符(解引用操作符)将获取指针所指的对象
给指针赋值和通过指针进行赋值
*sp1 = "a new value";
sp1 = sp2;
指针和引用的比较
都可间接访问另一个值
区别1.引用总是指向某个对象:定义引用时没有初始化是错误的
2.赋值行为的差异:给引用赋值修改的是该引用所关联的对象的值
而并不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义时初始化的原因)
C++使用**操作符指派一个指针指向另一个指针。
int ival = 1024;
int *pi = &ival; // pi points to an int
int **ppi = π // ppi points to a pointer to int
ival = *pi = **ppi
pi = *ppi
C++语言中,指针和数组密切相关。特别是在表达式中使用数组名时,该名字会自动转换为指向数组第一个元素的指针:
int ia[] = {0,2,4,6,8};
int *ip = ia; // ip points to ia[0]
两个指针减法操作的结果是标准库类型(library type)ptrdiff_t的数据。
与size_t类型一样,ptrdiff_t也是一种与机器相关的类型,在cstddef头文件中定义。size_t是unsigned类型,而ptrdiff_t则是signed整型。
允许在指针上加减0.
*解引用的操作符的优先级比加法操作符高
int *p = &ia[2];
int j = p[1]; // p[1] equivalent to *(p + 1)
p[1] is the same element as ia[3]
int k = p[-2]; // p[-2] is the same element as ia[0]
C++允许计算数组或对象的超出末端的地址,但不允许对此地址进行解引用操作
内置数组类型具有标准库容器的许多性质,与数组联合使用的指针本身就是迭代器。
指向const对象的指针(常用作函数的形参)
不允许用指针来改变其所指的const值
C++语言强制要求指向const对象的指针也必须具有const特性
const double *cptr; // cptr may point to a double that is const
cptr是一个指向double类型const对象的指针。
cptr本身并不是const。定义时不需要对它进行初始化
不能使用void*指针保存const对象的地址,而必须使用const void*类型的指针保存const对象的地址。
允许把非const对象的地址赋给指向const对象的指针
cptr一经定义,就不允许修改其所指对象的值。可用其他方法修改其所指的对象
不能保证指向const的指针所指对象的值一定不可修改
const指针定义时初始化
本身的值不能修改
int errNumb = 0;
int *const curErr = &errNumb; // curErr is a constant pointer
curErr是指向int型对象的const指针
不能使curErr指向其他对象
指向const对象的const指针
const double pi = 3.14159;
// pi_ptr is const and points to a const object
const double *const pi_ptr = π
既不能修改pi_ptr所指向对象的值,也不允许修改该指针的指向(即pi_ptr中存放的地址值)。
pi_ptr首先是一个const指针,指向double类型的const对象
指针和typedef
p112
字符串字面值的类型就是const char类型的数组
以空字符null结束的字符数组
C++语言通过(const)char*类型的指针来操纵C风格字符串
cstring这些标准库函数不会检查其字符串参数
strlen(s)返回s的长度,不包括字符串结束符null。若不是null结束,则值不确定
strcmp(s1,s2) strcat(s1,s2)strcpy(s1,s2)
strncat(s1,s2,n) strncpy(s1,s2,n) 更安全
if(cp1 < cp2) // compare addresses,not the values pointed to
比较在cp1和cp2中存放的地址
char largeStr[16 + 18 + 2]; // to hold cp1 a space and cp2
strncpy(largeStr , cp1, 17); // size to copy includes the null 16+ null
strncat(largeStr ," ",2); // pedantic,but a good habit null---> " null"
strncat(largeStr, cp2, 19); // adds at most 18 characters,plus a null
C风格字符串尽量避免使用
尽可能使用标准库类型string
string largeStr = cp1;
largeStr += " ";
largeStr += cp2;
标准库负责处理所有的内存管理问题
创建动态数组
每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间成为程序的自由存储区(free store)或堆(heap)
C++使用new和delete表达式在自由存储区中分配存储空间
int *pia = new int[10]; // array of 10 uninitialized ints
分配了一个含有10个int型元素的数组,并返回指向该数组第一个元素的指针,此返回值初始化了指针pia
在自由存储区中创建的数组对象是没有名字的,程序员只能通过其地址间接地访问堆中的对象
动态分配数组时,其元素只能初始化为元素类型的默认值。如果数组元素具有类类型,将使用该类的默认构造函数实现初始化;如果数组元素是内置类型,则无初始化
int *pia = new int[10]; // array of 10 uninitialized ints 无初始化
int *pia2 = new int[10](); // array of 10 uninitialized ints 数组元素做值初始化 值为0
const对象的动态数组必须初始化
已创建的常量元素不允许修改----因此这样的数组实际上用处不大
// error : uninitialized const array
const int *pci_bad = new const int[100];
// ok: value-initialized const array
const int *pci_ok = new const int[100]();
允许动态分配空数组
调用new动态创建长度为0的数组是合法的
char arr[0]; // error:cannot define zero-length array
char *cp = new char[0]; // ok : but cp can't be dereferenced
new返回有效的非零指针。不能进行解引用操作,因为没有指向任何元素
允许比较运算,指针加(减)0
cp没有指向任何对象,数组是空的
程序员必须显式地将其占用的存储空间返还给程序的自由存储区。
delete []pia; // 遗漏了[],编译器无法发现,程序将在运行时出错
回收了pia所指向的数组,把相应的内存返还给自由存储区
p121
const char *str = st2.c_str();// ok.。。。。。。。。。。。。。。。。。。
允许使用数组初始化vector对象
const size_t arr_size = 6;
int int_arr[arr_size] = {0 , 1 ,2 ,3 ,4 ,5 };
// ivec has 6 elements:each a copy of the corresponding element in int_arr
vector<int> ivec(int_arr,int_arr + arr_size);
也可以是数组的子集
vector<int> ive(int_arr+1,int_arr+4);
多维数组数组的数组
int ia[3][4];
int (*ip)[4] = ia; // ip points to an array of 4 ints
ip = &ia[2]; // ia[2] is an array of 4 ints
*ip是int[4]类型-----即ip是指向含有4个元素的数组的指针
int *ip[4]; // array of pointers to int
int (*ip)[4]; // pointer to an array of 4 ints
用typedef简化指向多维数组的指针 p124
typedef int int_array[4];
int_array *ip = ia;
const size_t rowSize = 3;
const size_t colSize = 4;
int ia[rowSize][colSize];
for(size_t i = 0 ; i != rowSize ; i++)
{
for(size_t j = 0 ; j != colSize ; j++)
{
ia[i][j] = i * colSize + j;
cout << ia[i][j] << " ";
}
cout << endl;
}
============================
typedef int int_array[4];
int_array *ip = ia;
for(int_array *p = ia ; p != ia + 3 ; ++p)
{
for(int *q = *p;q != *p + 4 ; ++q)
{
cout << *q << " ";
}
cout << endl;
}
const size_t colSize = 4;
int ia[rowSize][colSize];
for(size_t i = 0 ; i != rowSize ; i++)
{
for(size_t j = 0 ; j != colSize ; j++)
{
ia[i][j] = i * colSize + j;
cout << ia[i][j] << " ";
}
cout << endl;
}
============================
typedef int int_array[4];
int_array *ip = ia;
for(int_array *p = ia ; p != ia + 3 ; ++p)
{
for(int *q = *p;q != *p + 4 ; ++q)
{
cout << *q << " ";
}
cout << endl;
}
vector 类型所包含的元素通过迭代器来操纵,
类似的,指针则用于访问数组元素。
现代C++程序不应使用C风格字符串
typedef研究。。。。