c++看的知识点!(持续更新。。)
0.
在用指针的时候,所有的人的都要事先建立一个概念: 指针就是一种数据类型,它和int bool char等没有两样,int 存放的是整形数据,char 存放的字符, 指针存放的是某段内存的地址。 整形声明的时候用int,指针类型声明用int *, 双指针声明用int ** ,指针中的int 是指针所指内存的类型。 说指针指向哪个变量,其实就是说指针的值是该变量的内存地址。
1.
new/delete 对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数 malloc/free不行需要手写。
这是因为new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new的语句也可以有多种形式。
如果用new创建对象数组,那么只能使用对象的无参数构造函数。例如
Obj *objects = new Obj[100]; // 创建100个动态对象
不能写成
Obj *objects = new Obj[100](1);// 创建100个动态对象的同时赋初值1
2.
构造函数
没有返回值
没有类型
不能定义为虚函数
不能调用的唯一一个函数
可以重载
析构函数
无返回值
没有类型
可以定义为虚函数
可以调用
不可以重载
3.
C++语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。
C语言之中只有前两种
引用不占内存
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
(2)不能有NULL引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
以下是“值传递”的示例程序。由于Func1函数体内的x是外部变量n的一份拷贝,改变x的值不会影响n, 所以n的值仍然是0。
void Func1(int x)
{
x = x + 10;
}
…
int n = 0;
Func1(n);
cout << “n = ” << n << endl; // n = 0
以下是“指针传递”的示例程序。由于Func2函数体内的x是指向外部变量n的指针,改变该指针的内容将导致n的值改变,所以n的值成为10。
void Func2(int *x)
{
(* x) = (* x) + 10;
}
…
int n = 0;
Func2(&n);
cout << “n = ” << n << endl; // n = 10
以下是“引用传递”的示例程序。由于Func3函数体内的x是外部变量n的引用,x和n是同一个东西,改变x等于改变n,所以n的值成为10。
void Func3(int &x)
{
x = x + 10;
}
…
int n = 0;
Func3(n);
cout << “n = ” << n << endl; // n = 10
对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式象“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用”这东西?
答案是“用适当的工具做恰如其分的工作”。
指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。就象一把刀,它可以用来砍树、裁纸、修指甲、理发等等,谁敢这样用?
如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”,以免发生意外。比如说,某人需要一份证明,本来在文件上盖上公章的印子就行了,如果把取公章的钥匙交给他,那么他就获得了不该有的权利。
4.
#ifndef GRAPHICS_H // 防止graphics.h被重复引用
#define GRAPHICS_H
……
#endif
5.
#define 对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)
在C++ 程序中只使用co n st常量而不使用宏常量,即co n st常量完全取代宏常量。
6.
char strDest[12];
strcpy( strDest, “hello world”);
int length = strlen(strDest);
什么链式就是一连串写下来的意思。。。
其实,说白了,就是如果上面的字符串拷贝函数strcopy的返回值是void,那么,上面那句:
int length = strlen( strcpy( strDest, “hello world”) );
7.
return语句不可返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。例如
char * Func(void)
{
char str[] = “hello world”; // str的内存位于栈上
…
return str; // 将导致错误
}
8.
内存分配方式有三种:
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
9.
字符数组a的容量是6个字符,其内容为hello\0。a的内容可以改变,如a[0]= ‘X’。指针p指向常量字符串“world”(位于静态存储区,内容为world\0),常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句p[0]= ‘X’有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误。
char a[] = “hello”;
a[0] = ‘X’;
cout << a << endl;
char *p = “world”; // 注意p指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误
cout << p << endl;
10.
对于非内部数据类型的输入参数,应该将“值传递”的方式改为“co n st引用传递”,目的是提高效率。例如将void Func(A a) 改为void Func(c o n st A &a)。
对于内部数据类型的输入参数,不要将“值传递”的方式改为“co n st引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为void Func(co n s t int &x)。
11、多态分静态的多态和动态的多态
静态的多态:函数重载(函数返回类型不同或者函数个数不同、不同类函数完全一样)
动态的多态:利用虚函数实现

浙公网安备 33010602011771号