C++与GO的一些区别 | 青训营

141 阅读3分钟

1 new

C++: 使用new 会返回一个TreeNode类型的指针,并调用其构造函数来初始化对象。需要手动使用delete来释放内存。

TreeNode* node = new TreeNode()

GO:返回的也是一个指针,不过用法不一样。用于动态分配内存空间,并返回一个指向该类型零值的指针。不需要使用delete操作符来释放内存

var node *TreeNode = new(TreeNode)

2 自动类型推导

​ C++: 使用auto

auto node = new TreeNode()

​ GO: 使用 :=

node:= new(TreeNode)

3 函数

函数声明和定义的语法不同:GO 函数定义使用关键字 func,而 C++ 函数定义使用返回类型及函数名。

C++:

int add(int a, int b) {
    return a + b;
}

GO:

func add(a, b int) int {   
    return a + b
}

GO函数多返回值示例:

C++:

void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

GO:

func swap(a, b int) (int, int) {
//func函数关键字 | 函数名| 函数参数| 函数返回值类型| 
    return b, a
}

4指针

GO语言不支持指针的自增自减操作。这是因为在GO语言中,指针的使用相对比较严格,GO语言的设计者认为指针的自增自减操作容易引起混淆和错误,因此取消了这个操作符。

func test(){
    var numbers [2]int
	numbers[0] = 100
	numbers[1] = 200
	p := &numbers[0]
	fmt.Printf("p: %p,*p: %d\n", p, *p)  //p=0xc0000180e0,*p=100
    p += 1                          //报错 (mismatched types *int and untyped int) ,地址不能+1,因为go里面指针不能自增自减
	fmt.Printf("p: %p,*p: %d\n", p, *p)
}	

但是也有办法实现C++里面的操作,但是非常麻烦,需要导入 unsafe包。操作如下

import "unsafe"

var i int = 100
p := &i
p = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(1))) //类似C++里面的 p++
fmt.Printf("p: %v\n", p)  //这里地址会+1

进一步我们可以实现以下这个操作来实现指针操作数组:

func test() {
	var numbers [2]int
	numbers[0] = 100
	numbers[1] = 200
	p := &numbers[0]

	fmt.Printf("p: %p,*p: %d\n", p, *p)
	fmt.Printf("&numbers[1]: %p,numbers[1]: %d\n", &numbers[1], numbers[1])

	size := unsafe.Sizeof(numbers[1])
	fmt.Printf("int size: %d bytes\n", size)

	p = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(8))) //uintptr(1)是一个byte大小
	fmt.Printf("p: %p,*p: %d\n", p, *p)
}

输出如下:

p: 0xc0000180e0,*p: 100
&numbers[1]: 0xc0000180e8,numbers[1]: 200
int size: 8 bytes
p: 0xc0000180e8,*p: 200

总之比较复杂,尽量在go里面尽量避免指针加加减减。

5 结构体

在GO语言中,如果标识符(例如类型名、变量名、函数名等)的首字母是大写字母,那么它就是导出的(Exported),可以被其他包(Package)访问和使用。如果标识符的首字母是小写字母,则它是未导出的(Unexported),只能在当前包内访问和使用。即使结构体类型是导出的,结构体的成员变量如果首字母是小写字母,也是未导出的,只能在结构体定义所在的包内访问和使用。

// 导出的结构体类型
type Person struct {
    Name string
    Age int
}
// 未导出的结构体类型
type person struct {
    name string
    age int
}

在C++语言中,结构体可以定义成员函数,使用成员函数来操作结构体的成员变量。而在GO语言中,结构体可以定义方法(Method),使用方法来操作结构体的成员变量。方法定义需要在方法名前指定接收者类型,可以是值类型或指针类型。例如:

struct Person {
    // ... C++
    void setAge(int age) {
        this->age = age;
    }
}; 
type Person struct { //GO
    name string
    age int
}
func (p *Person) SetAge(age int) {
    
    p.age = age
}

GO绑定函数里面的第一个括号表示要绑定的结构体是Person,p是一个类似C++里面的this,通过p可以访问Person里面变量