注意以下细节
(1)###
int *ptr;
强调 *ptr 是一个int类型的值
int* ptr;
强调 int* 一种类型,是指向int的指针
(2)###
下面的代码中
int* p1, p2;
声明了一个指针 p1 和一个常规变量 p2,也就是说,对于每一个指针变量名,都需要使用一个 (*) 号:
int *p1, *p2;
(3)###
int *i_ptr;
double *f_ptr;
char *ch_ptr;
尽管他们都是指针,却是不同类型的指针(指针基于其它类型);
*i_ptr *f_ptr *ch_ptr 指向长度不同的数据类型,但它们本身的长度通常是相同的,即地址的长度。
(4)###
int higgens = 5;
int *pt = &higgens;
将pt(而不是*pt)的值设置为&higgens,即:
int higgens= 5;
int *pt;
pt = &higgens;
(5)###
警告:一定要在对指针使用解除引用操作符(*)之前,将指针初始化为一个确定的、适当的地址。
(6)###
给指针赋地址(数字整型)的一种方法,是强制类型转换:
int *pt;
pt = (int*)0x8000000;
(7)###
使用 new 和 delete 时,应遵守以下规则:
- 不要使用 delete 删除不是 new 分配的内存;
- 不要使用 delete 释放同一内存两次;
- 如果使用 new[] 为数组分配内存,则应使用 delete[] 来释放;
- 如果使用 new[] 为一个实体分配内存,则应使用 delete 来释放;
- 对空值指针使用 delete 是安全的。
(8)###
可以用指针代替数组名是因为:你可以修改指针的值,而数组名是常量:
pointername = pointername + 1; // right
arrayname = arrayname + 1; // error 是常量,不能进行赋值
(9)###
对数组名应用sizeof得到的是数组的长度,而对指针应用sizeof得到的是指针的长度(与平台相关,通常为4)。
(10)###
cout.setf(ios_base::boolalpha);
使其后的表达式的cout语句的结果以“bool”方式显示
(11)###
递增/递减操作符和指针(假设pt指向a[1])
*++pt; // 此时pt指向a[2]
++*pt; // “a[2]+1”
(*pt)++; // “a[2]++”
*pt++; // pt仍指向a[2],但是该语句完成后,pt的值为a[3]的地址
(12)###
可以使用如下方式读取标准输入
for (cin>>x; x==0 ; cin>>x); // 如果 x == 0 继续输入
(13)###
如果不对函数内部定义的变量进行初始化,该变量的值将是不确定的。这意味着该变量的值将是它被创建之前,该内存单元保存的值。
(14)###
C++ 通常的约定是,退出值为 0 则意味着程序运行成功,为非零则意味着存在问题。
(15)###
C++ 中,在可以使用数字转义序列或符号转义序列(如 \0x8 和 \b)时,应使用符号序列。数字表示与特定的编码方式(如 ASCII 码)相关,而符号表示适用于任何编码方式,其可读性也更强。
(16)###
如果你在学习 C++ 之前学习了 C 语言,并打算使用 #define 来定义符号常量,请不要这样做,而应使用 const。
(17)###
C++ 不提倡使用外部变量,但是提倡外部结构( struct )声明。另外,在外部声明符号常量通常更合理。
(18)###
警告:一定要在对指针应用解除引用操作符(*)之前,将指针初始化为一个确定的、适当的地址。这是关于指针的金科玉律。
(19)###
在 cout 和多数 C++ 表达式中,char 数组名、指向 char 的指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址。
(20)###
必须在声明引用时进行初始化(int & zdsTest = tiger;)。
(21)###
返回引用的函数实际上是被引用变量的别名。
(22)###
应避免返回当函数终止时不再存在的内存单元引用。
(23)###
结构的默认访问类型是 public,而类为 private。C++ 通常把结构限制为只表示纯粹的数据对象或没有私有部分的类。
(24)###
缺省形参值的说明次序:必须以从右向左的顺序来声明,并且缺省形参的右面不能有非缺省形参值的参数。因为调用时实参取代形参是从左向右的顺序。
(25)###
如果既可以通过初始化,也可以通过赋值来设置对象的值,则应采用初始化的方式。通常这种方式效率更高。举例:
Exam e1 = Exam("zds",25,12); // #1
Exam e2;
e2 = Exam("Toby",25,12); // #2
#1语句是初始化,它创建有指定值的对象,可能会创建临时对象(也可能不会);#2语句是赋值。像这样在赋值语句中使用构造函数总会导致在赋值前创建一个临时对象。
(26)###
在默认情况下,将一个对象赋给同类型的另一个对象时,C++ 将源对象的每个数据成员的内容复制到目标对象中相应的数据成员中。
(27)###
记住:接受一个参数的构造函数允许使用赋值句法来将对象初始化为一个值。例:
Exam zdsEx = value;
(28)###
要创建类对象数组,则这个类必须有默认构造函数。
(29)###
不要返回指向局部变量或临时对象的引用。函数执行完毕后,局部变量和临时对象将消失,引用将指向不存在的数据。
(30)###
在类声明中定义的函数,将自动成为内联函数。
(31)###
如果方法通过计算得到一个新的类对象,则应考虑是否可以使用类构造函数来完成这种工作。这样不仅可以避免麻烦,而且可以确保新的对象是按照正确的方式创建的。例如:
Exa Exa::zdsText(const Exa& bExa) const{
Exa zdsExa;
zdsExa.x = x + bExa.x;
zdsExa.y = y + bExa.y;
return zdsExa;
}
可以用如下“更好”的代码取代:
Exa Exa::zdsText(const Exa& bExa) const{
return Exa(x + bExa.x,y + bExa.y);
}
当然,我们的类中需要有对应 Exa(x + bExa.x, y + bExa.y) 的构造函数。
(32)###
只接受一个参数的构造函数定义了从参数到类类型的转换。但是如果使用关键字 explicit 限定了这种构造函数,则它就只能用于显示转换,否则也可以用于隐式转换。
(33)###
使用 delete 删除对象可以释放对象本身占用的内存,但并不能自动释放属于对象成员的指针指向的内存。因此,必须使用析构函数。在析构函数中使用 delete 语句可确保对象过期时,由构造函数使用 new 分配的内存被释放。
(34)###
指针策略是 C++ 内存管理理念的核心,它将地址视为指定的量,而将值视为派生量。一种特殊类型的变量——指针——用于存储值的地址。因此,指针名表示的是地址。* 操作符称为间接值或解除引用操作符,将其应用于指针,可以得到该地址处存储的值(这和乘法使用的符号相同;C++ 根据上下文来确定所指的是乘法还是解除引用)。
(35)###
* 操作符两边的空格是可选的。传统上,C 程序员使用这种格式:
int *ptr;
这里强调 *ptr 是一个 int 类型的值。而很多 C++ 程序员使用这种格式:
int* ptr;
这里强调的是 int* 是一种类型,是指向 int 的指针。在哪里添加空格对于编译器来说是没有任何区别的。不过:
int* ptr1,ptr2;
将创建一个指针(ptr1)和一个常规 int 变量(ptr2)。对于每个指针变量名,都需要使用一个 *
(36)###
虽然指针指向的数据类型的长度可能不同,但指针变量本身的长度通常是相同的。
(37)###
指针的危险
极其重要的一点是:在 C++ 中创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。为数据提供空间是一个独立的步骤,忽略这一步骤无疑是自找麻烦。
警告:一定要在对指针应用解除引用操作符(*)之前,将指针初始化为一个确定的、适当的地址。这是关于指针的金科玉律。
(38)###
要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型:
int* ptr;
ptr =(int*)0xB8000000;
(39)###
只能用 delete 来释放由 new 分配的内存。这并不意味着要使用用于 new 的指针,而是用于 new 的地址。不过,对空指针使用 delete 是安全的。
(40)###
可以修改指针的值,因为它是变量。但是不能修改数组名的值,因为数组名是常量。
(41)###
对数组名使用 sizeof 操作符得到的是数组的长度,而对指针应用 sizeof 得到的是指针的长度,即使指针指向的是一个数组。
(42)###
绝对不要对为被初始化为适当地址的指针解除引用。
(43)###
在 cout 和多数 C++ 表达式中,char 数组名、指向 char 的指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址。