最近学习算法和刷题基本都是用C++写的程序,在这个过程中,发现C++和Java在语法上有很多相同点,但也有很多不同点,而这些不同点对于已经掌握Java的程序员来说,理解C++代码可能会有些吃力甚至困难,在踩过了一个又一个坑后,我决定把这些不同记录下来,可能涵盖的不是很全,所以本文会持续更新。

零、目录

1. new关键字
2. C++实例化对象的几种方式
3. C++初始化表达式
4. C++构造函数后的冒号
5. C++中难以省略的分号;
6. C++中的::
7. C++中的*、&、->
8. C++函数前或者函数后的const
9. delete完成后需要将指针置为NULL

一、new关键字

// C++中:
MyClass* a = new MyClass();
delete a;
// Java中:
MyClass a = new MyClass();
  1. C++中new关键字实例化对象之后返回的是一个对象的指针,所以需要定义指针;而Java中定义对象时返回的其实也是一个指针(引用),但是在Java中不需要显示的定义指针。

    不同点
  2. C++中通过new关键字实例化的对象在使用完毕后需要使用delete关键字手动释放内存;而Java中由于垃圾回收机制的存在,我们无需手动释放内存。

二、C++实例化对象的两种方式

// 方式一
MyClass* a = new MyClass();
delete a;
// 方式二
MyClass b(params...); // 该方式将会调用有参数的构造函数
MyClass c; //该方式将会调用无参数的构造函数
  1. 方式一中new关键字做了三件事:首先在堆内存上获得内存空间(类似malloc函数),然后调用类的构造函数,最后返回该内存空间的指针;因为是在堆内存的动态分配的内存空间,所以最后需要调用delete函数释放这一部分内存空间。
  2. 方式二中直接在栈内存上分配了存储空间,类似于基本类型的定义,所以无需手动释放内存空间,其会在作用域生命周期结束时自动调用析构函数释放内存;但是当对象信息量较大时,这种做法会占用很多内存,影响程序效率。

三、C++初始化表达式

int a(10); // 等效于 int a = 10;

与java不同,C++除了使用赋值语句初始化变量之外,还可以使用上述初始化表达式对变量进行初始化,其效果相同。

四、C++构造函数后的冒号

// 初始化表达式
class MyClass {
public:
const int a;
int b;
MyClass(int aVal, int bVal):a(aVal), b(bVal) {}
};
// 非初始化表达式,无法通过编译,编译时会报以下错误:
// 'const int MyClass::a' should be initialized
class MyClass {
public:
const int a;
int b;
MyClass(int aVal, int bVal) {
a = aVal;
b = bVal;
}
};

这个语法其实就是上述第四点中的初始化表达式,但这里我们看到下面这种赋值方式在构造函数里面会报错,这又是为什么呢?因为这里我们的冒号初始化和赋值语句干的事情不太一样:在冒号初始化时,只有冒号后面有相应变量的初始化表达式,就会在为成员变量分配内存时进行初始化,所以常量a在分配内存时做了初始化操作,之后也没有被改变值,所以不会报错;而在使用赋值语句时,构造函数在执行到函数体时已经为a分配了内存但却没有对其进行初始化,因此就会报should be initialized编译错误了。

这种神奇的写法我第一次见的时候也是惊讶了一波。

五、C++中难以省略的分号;

在上面例子中我们看到了C++类的定义后面也要加分号;我们知道在Java中类定义的大括号后面都无需加分号。

之后查资料发现:

在C++中,除函数,及预编译指令外,其它的语句或代码段结尾都必须要加分号。其中预编译指令是指,以#开头的语句。常见的有,#include ,#define, #ifdef, #if, #elif, #else,#endif等。

六、C++中的::(作用域符)

C++的作用域符::用法有三,一一介绍如下

  1. 全局作用域符
int a = 3;
void test() {
int a = ::a;
cout << a << endl;
}

这里就是将全局变量a的值通过全局作用域符的方式访问到,然后将其值赋给test函数中的局部变量a。

2. 类作用域符

class MyClass {
public:
void sayHello();
};
void MyClass::sayHello() {
cout << "hello world!" << endl;
}

这里有点类似Java中定义接口和对接口进行实现;首先在类的定义中定义了一个函数sayHello,但是没有具体函数体,然后在类的定义外,通过作用域符,在函数sayHello前加了一个MyClass::,相当于告诉编译器,这个函数就是MyClass类的sayHello方法的具体实现。

3. 命名空间作用域符

std::cout << "hello world!" << endl;

这里std就是命名空间,这样的用法相当于using namespace std;

七、C++中的*、&、->

class MyClass {
public:
int a;
MyClass(int aVal):a(aVal){}
};
int main () {
MyClass obj(5);
MyClass* objPointer = new MyClass(3);
// 常规操作
cout << obj.a << endl;
// 取指针操作
cout << (*objPointer).a << endl;
// ->操作
cout << objPointer->a << endl;
// 取地址操作
cout << (&obj)->a << endl;
// new出来的对象别忘了释放内存哦
delete objPointer;
return 0;
}

在C++中:

  1. *表示访问指针a指向的变量;
  2. &表示取得变量的地址;
  3. .表示访问对象的的成员变量或者函数;(与Java相同)
  4. ->表示访问指针指向的对象的成员变量或者函数;

指针内容实在太多,这里就不赘述了,有兴趣的童鞋可以参考菜鸟教程

八、C++函数名前或者函数名后的const

  1. 函数名前的const
const int getVal() {
const int a = 3;
return a;
}
int main() {
cout << getVal() << endl;
}

就是定义函数的返回类型,规定返回变量类型必须为const。

2. 函数名后的const(用于类的成员函数中)

class MyClass {
public:
int a;
MyClass(int aVal):a(aVal){}
void sayHello() const {
cout << "a value is: " << a << endl;
}
// 编译报错:assignment of member 'MyClass::a' in read-only object
void changeA() const {
a = 5;
}
};

函数名后面的const表示是该函数为常成员函数,该函数不能修改对象内的任何成员变量,只能发生读操作,不能发生写操作。这样可以对成员变量起到保护作用。

九、delete完成后需要将指针置为NULL

MyClass* a = new MyClass();
delete a;
// 省略下面这句运行时会出现以下错误:
// pointer being freed was not allocated
a = NULL;
delete a;

对一个非空指针delete后,若没有置为NULL,若再次delete的话,有可能出现问题。而C++标准规定:delete空指针是合法的,没有副作用。所以每次delete之后要将指针的值置为NULL。这是一个不得不养成的好习惯,hah...

C++与Java语法上的不同的更多相关文章

  1. Java语法糖1:可变长度参数以及foreach循环原理

    语法糖 接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的 ...

  2. 一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库 RxJava,相当好

    https://github.com/ReactiveX/RxJava https://github.com/ReactiveX/RxAndroid RX (Reactive Extensions,响 ...

  3. 程序员带你学习安卓开发,十天快速入-对比C#学习java语法

    关注今日头条-做全栈攻城狮,学代码也要读书,爱全栈,更爱生活.提供程序员技术及生活指导干货. 如果你真想学习,请评论学过的每篇文章,记录学习的痕迹. 请把所有教程文章中所提及的代码,最少敲写三遍,达到 ...

  4. Gradle在大型Java项目上的应用

    在Java构建工具的世界里,先有了Ant,然后有了Maven.Maven的CoC[1].依赖管理以及项目构建规则重用性等特点,让Maven几乎成为Java构建工具的事实标准.然而,冗余的依赖管理配置. ...

  5. c#语法与c++ 及 java语法的对比分析

    早期开发的时候一直用c/c++,后来主要用的是java.最近需要用下c#. 熟悉了下c#,发现c#语言在对c/c++基础上做了很多简化,同时参考了很多java的语法习惯,本来在语法上c/c++就有很多 ...

  6. JAVA平台上的网络爬虫脚本语言 CrawlScript

    JAVA平台上的网络爬虫脚本语言 CrawlScript 网络爬虫即自动获取网页信息的一种程序,有很多JAVA.C++的网络爬虫类库,但是在这些类库的基础上开发十分繁琐,需要大量的代码才可以完成一 个 ...

  7. Java语法之反射

    一.反射机制 在前面Java语法之注解自定义注解时我们也有提到反射,要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象.那什么是反射呢?JAVA反射机制是在运行状 ...

  8. Java语法知识总结

    一:java概述: 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名为Java: ...

  9. Java语法糖设计

    语法糖 Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这 ...

随机推荐

  1. linux中进程亲和性绑定

    什么是绑核所谓绑核,其实就是设定某个进程/线程与某个CPU核的亲和力(affinity).设定以后,Linux调度器就会让这个进程/线程只在所绑定的核上面去运行.但并不是说该进程/线程就独占这个CPU ...

  2. heartbeat安装配置

    一.环境 node01 192.168.127.101 心跳:192.168.42.101 node02 192.168.127.102 心跳:192.168.42.102 虚拟ip:192.168. ...

  3. 气泡小角的css实现

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> ...

  4. CSS3-transform-style

    transform-style属性 transform-style属性是3D空间一个重要属性,指定嵌套元素如何在3D空间中呈现.他主要有两个属性值:flat和preserve-3d. transfor ...

  5. (转)git clone: error: RPC failed; result=18, HTTP code = 200 解决办法

    git clone: error: RPC failed; result=18, HTTP code = 200 解决办法 分类: git2013-09-01 17:03 10753人阅读 评论(2) ...

  6. ZOJ 2058 The Archaeologist's Trouble II(贪心+模拟)

    [题目大意] 一个n高的塔,由@ * ?三种字符组成.每行相邻两个字符不能相邻. '?' 表示未确定是 '@' 还是 '*' . 求'@' 可能出现的最多和最少次数. [分析] 在可以填的情况下 先填 ...

  7. hdu 5878

    I Count Two Three Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. IntelliJ IDEA 类和方法注释的生成以及Javadoc的简单使用记录

    idea,设置类注释和,方法注释的常见的设置方法(不同的版本设置方法有所偏差,简单记录一些目前自己在使用的方法,) 方法注释:在keyMap中搜索Fix doc comment ,后点击右键设置一个快 ...

  9. Android开发调试无法连接到夜神模拟器的解决方法

    Android开发调试无法连接到夜神模拟器的解决方法: 一般原因是adb的版本不一致造成的!!!!!换成一样的就可以了. 在网上看到的方法,特记录下来: 1.任务管理器里看下,adb.exe以及nox ...

  10. spring常用的注解

    一.使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包). <context:component-scan base-package="cn.test& ...