指针数组
知识点
数组名其实就是指向数组第0个元素的指针。但是,不能修改“数组名”这个指针的值,即它是常量指针。
int a[] = {1, 2, 3}; *a; // 等同于a[0] *(a + n); // 等同于a[n] int *p = a + 1; *p; // 2 *(p + 1); // 3
知识点
当指针指向数组元素时,加减法才有意义。
可以对指针加上或者减去一个整数。这表示:将指针在数组中向前或向后移动若干位置。
当两个指针指向同一个数组时,可以对两个指针做减法。这表示两个指针所指向元素在数组中的距离。
p = p + 1; // *p == 3 p = p - 1; // *p == 2 cout << p - a << endl; // 1 指针在偏移后不能超过数组的范围。当对超过数组范围的指针解引用时,行为未定义(可能出现运行时错误)。 同样,也不要对不在同一个数组内的两个指针执行减法。 //题目描述: //实现函数`productMinMax`,返回数组中最小值和最大值的积。 //保证结果不会超过int范围。 //输入:无 //输出:`-90` #include <iostream> int productMinMax(int *arr, int len) { int minV = *arr, maxV = *arr; for (int *p = arr + 1; p < arr + len; ++p) { if (minV > *p) minV = *p; if (maxV < *p) maxV = *p; } return minV * maxV; } int main() { int arr[] {1, 5, -4, 3, 2, 10, -3, -9, -8}; std::cout << productMinMax(arr, sizeof(arr) / sizeof(int)) << std::endl; }
动态内存分配
知识点
new Type在堆(程序的静态存储区)上新建一个对象,返回指向这个对象的指针。
new Type[cnt] 在堆上新建一个长为cnt,类型为Type的数组,返回这个数组的首指针。
new运算符的初始化:
int *p1 = new int; // *p1为不确定的任意值
int *p2 = new int(3); // *p1 == 3
int *p3 = new int(); // *p1 被初始化为0
int *p4 = new int[4]; // p4数组的所有元素为不确定值
int *p5 = new int[4] {1, 2, 3, 4}; // 用花括号列表初始化
int *p6 = new int[4] (); // p6数组的所有元素被初始化为0
int *p7 = new int[4] {1}; // 注意:p7数组仅有第0个元素为1;其余元素都被初始化为0
无论如何,不建议依赖上文中“初始化为0”的语法,这会增加debug的难度。所有new得到的元素应该被显式初始化。
delete ptr 和 delete ptr[] 可以释放ptr对应的内存。
如果ptr并不指向 new 的内存,程序会发生运行时错误
如果已经 new 的内存未被 delete,则发生内存泄漏
当new操作失败(如系统内存耗尽),它返回nullptr。使用new时建议检测是否成功。
动态变量实例
知识点
使用传统的数组,我们只能在源代码中就写好数组的大小,不能修改;
通过申请动态数组,我们可以在运行时控制数组的大小。
指针与字符串
知识点
字符串也是储存在数组中的。可以把字符串常量赋值给数组来初始化。
由于字符串的最后一个字节一定为'\0',只要得到数组的首指针,就可以遍历整个字符串。
char ss[] = "abc", *str = ss; char *str1 = new char[10]; strcpy(str1, "abc"); //输出ss,等价于cout << ss << endl; for (char *p = ss; *p != 0; ++p) { cout << *p; } cout << endl;
也可以把字符串常量赋给 const char* 指针。因为字符串常量的每一个字符不可以修改,使用了 const 修饰符。但这是较陈旧的用法,不建议使用。如果不使用 const,严格说是错误的(编译器会提示warning,但可以运行),此时若修改字符串的任一位,行为未定义(undefined)。
const char *s1 = "hello"; // ok, deprecated char *s2 = "world"; // warning: ISO C++ forbids converting a string constant to ‘char*’ //题目描述: //实现函数`myStrcmp`,比较两个输入的字符串。 //如果第一个字符串字典序小于第二个,返回-1;如果字典序相同,返回0;如果第一个字符串字典序大于第二个,返回1。 //输入:无 //输出:`-1` #include <iostream> int myStrcmp(const char *s1, const char *s2) { while (*s1 && *s2) { if (*s1 < *s2) { return -1; } else if (*s1 > *s2) { return 1; } s1++; s2++; } if (*s1) { return 1; } else if (*s2) { return -1; } else { return 0; } } int main() { char s1[] = "abcde", s2[] = "abcef"; std::cout << myStrcmp(s1, s2) << std::endl; }