C++ 语言提供了两种类似于 vector 和迭代器类型的低级复合类型——数组和指针(二者为内置数据类型)。应尽量使用vector和iterator
2.数组的维数必须用值大于等于1的常量表达式定义。此常量表达式只能包含整型字面值常量、枚举常量或者用常量表达式初始化的整型 const 对象。非 const 变量以及要到运行阶段才知道其值的 const 变量都不能用于定义数组的维数。所以运行时才知道维数的情况是不也以定义数组的,这时使用vector
3.显式初始化的数组不需要指定数组的维数值,编译器会根据列出的元素个数来确定数组的长度
4.字符数组
5.数组不允许直接复制和赋值。所以数组不能像vector那样直接初始化。对数据类型,首先就要考虑如何对其进行初始化。然后考虑作用在其上的操作。string和vector支持复制和赋值,同时也支持关系操作符! !!!注意:string和vector的关系操作符均遵循下列规则:根据第一个不匹配的元素来比较!null小!
vector 的遍历可使用下标或迭代器实现,同理,也可用下标或指针来遍历数组。指针是指向某种类型对象的复合数据类型,是用于数组的迭代器:指向数组中的一个元素。在指向数组元素的指针上使用解引用操作符 *(dereference operator)和自增操作符 ++(increment operator),与在迭代器上的用法类似。
指针
指针的概念很简单:指针用于指向对象。与迭代器一样,指针提供对其所指对象的间接访问,只是指针结构更通用一些。与迭代器不同的是,指针用于指向单个对象,而迭代器只能用于访问容器内的元素。具体来说,指针保存的是另一个对象的地址
指针和数组容易产生不可预料的错误。其中一部分是概念上的问题:指针用于低级操作,容易产生与繁琐细节相关的(bookkeeping)错误。其他错误则源于使用指针的语法规则,特别是声明指针的语法。
指针可以进行赋值(0或NULL或其他指针;允许把数值 0 或在编译时可获得 0 值的 const 量赋给指针。关键是要使指针获得有效地址。0指只是告诉编译器指针未初始化;NULL是从c继承下来的预处理器变量,其值为0,预处理时会将NULL替换为0)
由于指针的类型用于确定指针所指对象的类型,因此初始化或赋值时必须保证类型匹配。
避免未初始化的指针!对大多数的编译器来说,如果使用未初始化的指针,会将指针中存放的不确定值视为地址通常会导致程序崩溃。C++ 语言无法检测指针是否未被初始化,也无法区分有效地址和由指针分配到的存储空间中存放的二进制位形成的地址
void* 指针可以保存任何类型对象的地址,表明该指针与一地址值相关,但不清楚存储在此地址上的对象的类型。
void* 指针只支持几种有限的操作:与另一个指针进行比较;向函数传递 void* 指针或从函数返回 void* 指针;给另一个 void* 指针赋值。不允许使用 void* 指针操纵它所指向的对象。
指针操作 :
1.dereference(*)
2.对指针赋值就是修改指针指向的对象,而使用解引用指针作为左操作数进行赋值则修改的是指针指向对象的值。给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义时初始化的原因)。
3.指针可以进行算术操作。在指针上加一个整型数值,其结果仍然是指针。允许在这个结果上直接进行解引用操作,而不必先把它赋给一个新指针。两个指针可以进行减操作,以后得到ptrdiff_t类型的二者差几个对象
C++ 语言中,指针和数组密切相关。特别是在表达式中使用数组名时,该名字会自动转换为指向数组第一个元素的指针。在使用下标访问数组时,实际上是对指向数组元素的指针做下标操作。只要指针指向数组元素,就可以对它进行下标操作:
C++ 允许计算数组或对象的超出末端的地址 ,但不允许对此地址进行解引用操作。而计算数组超出末端位置之后或数组首地址之前的地址都是不合法的。例如:vector的end;
使用指针遍历数组如下:C++ 允许使用指针遍历数组。和其他内置类型一样,数组也没有成员函数
const限定符表示的概念的复习与加深 :
const对象是只读的,所以必须初始化。非const对象的值可以赋值给const对象,但是反过来不行!!
vector<T>::const_iterator itr说明迭代器指向的对象是const的
而const vector<T>::iterator itr 说明迭代器本身是const的
const int *p p指向的对象是const的;int* const p p本身是const的
指向 const 的指针 cptr 实际上指向了一个非 const 对象。尽管它所指的对象并非 const,但仍不能使用 cptr 修改该对象的值。本质上来说,由于没有方法分辩 cptr 所指的对象是否为 const,系统会把它所指的所有对象都视为 const。
如果指向 const 的指针所指的对象并非 const,则可直接给该对象赋值或间接地利用普通的非 const 指针修改其值:毕竟这个值不是 const。重要的是要记住:不能保证指向 const 的指针所指对象的值一定不可修改。
在实际的程序中,指向 const 的指针常用作函数的形参。将形参定义为指向 const 的指针,以此确保传递给函数的实际对象在函数中不因为形参而被修改。
指针和typedef
typedef string *pstring;
const pstring cstr;
把cstr理解为 const string *cstr;是错误的,原因在于将typedef当作文本扩展了。声明 const pstring 时,const 修饰的是 pstring 的类型,这是一个指针。所以应该理解为string *const cstr;这里没有初始化!const对像必须初始化
const限定符修饰谁很关键。const 限定符既可以放在类型前也可以放在类型后:
c风格字符串 :以空字符null结束的const char字符数组,而string不是以空字符结尾的 ,c_str()可以返回c风格字符串(const char*);string与c风格字符串转换问题主要出现在调用别人写的函数时。但是如果函数是fun(char*)使用c_str()则不行;这时使用copy(char *buf,size_type num,size_type index)则把字符串的内容复制或写入既有的c_string或 字符数组内,这里的buf要事先分配好内存空间malloc()。注意自己实现的函数坚持使用c++风格,一般c风格程序也应该使用const char*作为形参!
string本质上是一个容器
typedef basic_string <char> string;
typedef basic_string <wchar_t> wstring;
cstring 是 string.h 头文件的 C++ 版本,而 string.h 则是 C 语言提供的标准库。
cstring提供的函数假定它们所修改的字符串具有足够大的空间接收本函数新生成的字符,程序员必须确保目标字符串必须足够大 。比如copy的例子。这个足够的空间如何满足:1,定义目标字符串时已经分配足够的空间;2.重新分配空间
要加深数组与指针的密切关系的理解。用c风格字符串不一定总是用char*,也可以使用char[]。
c++的string支持关系操作符;而c风格字符串的比较必须使用cstring库中的strcmp()函数;类似的还有strcat
重申!设计到c风格字符串的复制;连接等操作均要保证目标缓冲区具有足够大的空间!!!!
这里要坚持一种分格。对目标字符串我们要事先分配空间,然后随着程序的进行再使用realloc重新设定空间,若一开始未指定空间,realloc失败,其必须知道旧空间大小!!。
方法一:
方法二:
总结:
字符串字面值是c风格字符串的实例,永远不要忘记字符串结束符 null,这对标准库函数的实现影响!
标准库函数 strlen 总是假定其参数字符串以 null 字符结束,当调用该标准库函数时,系统将会从实参 ca 指向的内存空间开始一直搜索结束符,直到恰好遇到 null 为止。strlen 返回这一段内存空间中总共有多少个字符,无论如何这个数值不可能是正确的。
如果必须使用 C 风格字符串,则使用标准库函数 strncat 和 strncpy 比 strcat 和 strcpy 函数更安全,特别是在复制和串连字符串时,一定要时刻记住算上结束符 null。在定义字符串时要切记预留存放 null字符的空间
创建动态数组
数组类型的变量有三个重要的限制:数组长度固定不变,在编译时必须知道其长度,数组只在定义它的块语句内存在。实际的程序往往不能忍受这样的限制——它们需要在运行时动态地分配数组。虽然数组长度是固定的,但动态分配的数组不必在编译时知道其长度,可以(通常也是)在运行时才确定数组长度。与数组变量不同,动态分配的数组将一直存在,直到程序显式释放它为止,在不使用分配的地址之前不能delete。
使用new/delete c中使用malloc/free。实质上new是在堆上动态分配内存
C++ 虽然不允许定义长度为 0 的数组变量,但明确指出,调用 new 动态创建长度为 0 的数组是合法 的:
使用数组初始化vector
另外两个例子:加深对指针类比于迭代器和new/delete.
例二:
这个例子是对new/delete对的理解。不是说new一个就要跟着一个delete,实质是对new的堆空间进行delete,所以这里delete parr[ix]就是delete了char *p = new char[(*iter).size()+1]分配的空间
多维数组其实就是数组的数组 ,所以由多维数组转换而成的指针类型应是指向第一个内层数组的指针。
用 typedef 简化指向多维数组的指针
可使用 typedef 类型输出 ia 的元素:
本文详细介绍了C++中的数组和指针概念,包括数组的定义与初始化、数组与指针的关系、指针的基本操作及注意事项。同时,文章还探讨了如何使用指针遍历数组、const限定符的使用、C风格字符串处理以及动态数组的创建。
4664

被折叠的 条评论
为什么被折叠?



