一、new关键字
1 | // C++中: |
- C++中new关键字实例化对象之后返回的是一个对象的指针,所以需要定义指针;而Java中定义对象时返回的其实也是一个指针(引用),但是在Java中不需要显示的定义指针。
不同点 - C++中通过new关键字实例化的对象在使用完毕后需要使用delete关键字手动释放内存;而Java中由于垃圾回收机制的存在,我们无需手动释放内存。
二、C++实例化对象的两种方式
1 | // 方式一 |
- 方式一中new关键字做了三件事:首先在堆内存上获得内存空间(类似malloc函数),然后调用类的构造函数,最后返回该内存空间的指针;因为是在堆内存的动态分配的内存空间,所以最后需要调用delete函数释放这一部分内存空间。
- 方式二中直接在栈内存上分配了存储空间,类似于基本类型的定义,所以无需手动释放内存空间,其会在作用域生命周期结束时自动调用析构函数释放内存;但是当对象信息量较大时,这种做法会占用很多内存,影响程序效率。
三、C++初始化表达式
1 | int a(10); // 等效于 int a = 10; |
与java不同,C++除了使用赋值语句初始化变量之外,还可以使用上述初始化表达式对变量进行初始化,其效果相同。
四、C++构造函数后的冒号
1 | // 初始化表达式 |
这个语法其实就是上述第四点中的初始化表达式,但这里我们看到下面这种赋值方式在构造函数里面会报错,这又是为什么呢?因为这里我们的冒号初始化和赋值语句干的事情不太一样:在冒号初始化时,只有冒号后面有相应变量的初始化表达式,就会在为成员变量分配内存时进行初始化,所以常量a在分配内存时做了初始化操作,之后也没有被改变值,所以不会报错;而在使用赋值语句时,构造函数在执行到函数体时已经为a分配了内存但却没有对其进行初始化,因此就会报should be initialized编译错误了。
这种神奇的写法我第一次见的时候也是惊讶了一波。
五、C++中难以省略的分号;
在上面例子中我们看到了C++类的定义后面也要加分号;我们知道在Java中类定义的大括号后面都无需加分号。
之后查资料发现:
在C++中,除函数,及预编译指令外,其它的语句或代码段结尾都必须要加分号。其中预编译指令是指,以#开头的语句。常见的有,#include ,#define, #ifdef, #if, #elif, #else,#endif等。
六、C++中的::(作用域符)
C++的作用域符::用法有三,一一介绍如下
- 全局作用域符
1 | int a = 3; |
这里就是将全局变量a的值通过全局作用域符的方式访问到,然后将其值赋给test函数中的局部变量a。
- 类作用域符
1 | class MyClass { |
这里有点类似Java中定义接口和对接口进行实现;首先在类的定义中定义了一个函数sayHello,但是没有具体函数体,然后在类的定义外,通过作用域符,在函数sayHello前加了一个MyClass::,相当于告诉编译器,这个函数就是MyClass类的sayHello方法的具体实现。
- 命名空间作用域符
1 | std::cout << "hello world!" << endl; |
这里std就是命名空间,这样的用法相当于using namespace std;
七、C++中的*、&、->
1 | class MyClass { |
在C++中:
*表示访问指针a指向的变量;
&表示取得变量的地址;
.表示访问对象的的成员变量或者函数;(与Java相同)
->表示访问指针指向的对象的成员变量或者函数;
指针内容实在太多,这里就不赘述了,有兴趣的童鞋可以参考菜鸟教程
八、C++函数名前或者函数名后的const
- 函数名前的const
1 | const int getVal() { |
就是定义函数的返回类型,规定返回变量类型必须为const。
- 函数名后的const(用于类的成员函数中)
1 | class MyClass { |
函数名后面的const表示是该函数为常成员函数,该函数不能修改对象内的任何成员变量,只能发生读操作,不能发生写操作。这样可以对成员变量起到保护作用。
九、delete完成后需要将指针置为NULL
1 | MyClass* a = new MyClass(); |
对一个非空指针delete后,若没有置为NULL,若再次delete的话,有可能出现问题。而C++标准规定:delete空指针是合法的,没有副作用。所以每次delete之后要将指针的值置为NULL。这是一个不得不养成的好习惯.