C++与Java语法上的不同

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

最近学习算法和刷题基本都是用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();
  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。

  1. 类作用域符
class MyClass {
  public:
    void sayHello();
};
void MyClass::sayHello() {
  cout << "hello world!" << endl;
}

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

  1. 命名空间作用域符
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。

  1. 函数名后的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...

目录
相关文章
|
16天前
|
Java API C++
Java JNI开发时常用数据类型与C++中数据类型转换
Java JNI开发时常用数据类型与C++中数据类型转换
22 0
|
8天前
|
Java Go C#
编程语言C#、C++、Java、Python、go 选择哪个好?
我想说的是,不论选择哪种编程语言,决定选择的都是你最终的目的,做选择之前,先充分调研每一个选择项,再做选择思路就会非常清晰了。
25 3
|
9天前
|
Java
哇塞!Java 基本语法的运算符,你真的懂了吗?算术运算符篇
【6月更文挑战第14天】Java中的算术运算符是编程基础,包括加法`+`(用于数字相加和字符串拼接)、减法`-`、乘法`*`、除法`/`(需防除数为零)和取余`%`。它们在计算位移、周期性问题等场景中广泛应用。理解并熟练掌握这些运算符,能提升编程效率和代码质量。现在就开始实践,发掘它们的更多可能性吧!
|
9天前
|
Java
惊人!关系运算符对 Java 基本语法的影响超乎想象!
【6月更文挑战第14天】Java中的关系运算符是编程基础的关键,如&quot;==&quot;、&quot;!=&quot;、&quot;&gt;&quot;、&quot;&lt;&quot;、&quot;&gt;=&quot;和&quot;&lt;=&quot;。它们在条件判断中扮演重要角色,控制程序流程并依据数据作出响应。从比较数值到构建复杂的逻辑,如购物车优惠条件或游戏关卡判定,关系运算符在实际项目中广泛应用。理解并熟练使用这些运算符能增强程序的灵活性和智能性,开启更丰富的编程可能。
|
9天前
|
Java C++
java和C++的标志符可以是中文(虽然不提倡)
java和C++的标志符可以是中文(虽然不提倡)
|
9天前
|
存储 Java
震惊!关系运算符在 Java 基本语法中竟然这么重要!
【6月更文挑战第14天】Java 中的关系运算符在编程中扮演关键角色。通过案例展示了它们的用法:比较数值大小、判断字符串相等、执行多重关系判断、在循环和条件语句中的应用,以及与其他运算符结合使用。理解并熟练运用这些运算符,能有效控制程序流程,实现复杂逻辑,是构建 Java 代码基础的重要部分。
|
9天前
|
算法 Java 程序员
厉害了!算术运算符,让 Java 基本语法大不同!
【6月更文挑战第14天】Java中的算术运算符是编程基础,如加法&quot;+&quot;不仅用于数字相加,也可拼接字符串。减法&quot;-&quot;、乘法&quot;*&quot;、除法&quot;/&quot;(注意除数非零)、取余 &quot;%&quot; 在各种计算中扮演重要角色。例如,乘法可计算物体移动距离,取余用于数据分组,加减法在复杂公式中必不可少。熟练运用这些运算符能提升代码效率和逻辑性,助力成为更出色的Java程序员。
|
9天前
|
Java 数据安全/隐私保护
尖叫!逻辑运算符如何重塑 Java 基本语法!
【6月更文挑战第14天】Java编程中的逻辑运算符(&&, ||, !)是构建复杂逻辑的关键。与运算符要求两边表达式均真,或运算符只需一侧为真,非运算符则对布尔值取反。在实际应用如登录检查、条件判断中,这些运算符组合使用能实现灵活的控制流程。理解并熟练运用逻辑运算符,能增强程序的逻辑处理能力,为编程带来广阔的可能性。探索和实践,让逻辑运算符在代码中释放更大潜力!
|
9天前
|
Java
恐怖!不懂算术运算符,还敢说懂 Java 基本语法?
【6月更文挑战第14天】Java中的算术运算符是编程基础,包括加法`+`、减法`-`、乘法`*`、除法`/`和取余`%`。它们不仅用于基本数学计算,还在复杂程序逻辑中扮演重要角色。例如,计算图形面积、游戏得分管理等场景。理解并熟练运用这些运算符是成为Java高手的关键,它们构成程序的基础并赋能复杂计算。不断深化对算术运算符的掌握,将助力我们编写更高效、精准的Java程序。