目录
前言
目前做了很多项目,接触到各种语言,基本上用什么学什么,语言的边际就会很模糊,实际上语言的设计大同小异,只是语言具备各自的特性区别。其中一个重要的概念是指针,这个在C语言就风靡的技术,实际上在各个语言或显示或隐世的体现出来,而且在函数或者方法栈的调用展现本质相同的现象。相对而言Golang和Java在设计的时候差不多,C++概念真多。
C++
C++的指针,指针拓展至C,实际上默认情况下C++的指针类似go或者Java的引用,但是有特殊的定义,比如常量指针,指针常量,还有引用,demo如下。
堆指针
C++有栈对象和堆对象内存分配的说法,堆对象的指针需要手动回收。
#include <iostream>
using namespace std;
class Person{
int age;
string name;
public:
Person(){
}
Person(string name, int age){
this->name = name;
this->age = age;
}
string sayHello(){
return name + " : " + to_string(age);
};
};
void setPerson(Person* person){
delete person;
new Person("tom", 35);//省略写法,默认就会对person赋值
// Person p;
// person = &p;
};
int main(){
Person* person = new Person("JIM", 33);
setPerson(person);
string result = person->sayHello();
cout << result << endl;
delete person;
return 0;
}
随意写了一个类,使用指针访问,当然也可以创建栈对象,取地址,结果如下
TOM : 35
在指针的时候,即使在方法栈中赋值也会影响数据的改变,这个在Golang和Java中是不存在的,当然Golang类似C语言,可以使用指针的指针模拟这种情况,这就是为什么说Golang是最接近C语言的,C语言也是这么做的。 笔者也写了其他文章:go 函数或者方法参数调用的过程_fenglllle的博客-CSDN博客
栈指针
如果使用栈对象,不需要手动回收内存,引用计数法自动回收
#include <iostream>
using namespace std;
class Person{
int age;
string name;
public:
Person(){
}
Person(string name, int age){
this->name = name;
this->age = age;
}
string sayHello(){
return name + " : " + to_string(age);
};
};
void setPerson(Person* person){
//delete person;
// new Person("tom", 35);
Person p("TOM", 35);
person = &p;
};
int main(){
Person person = Person("JIM", 33);
setPerson(&person);
string result = person.sayHello();
cout << result << endl;
//delete person;
return 0;
}
结果就跟Java的模式一样
JIM : 33
如果直接修改地址的值,那么是可以修改的
#include <iostream>
using namespace std;
class Person{
int age;
string name;
public:
Person(){
}
Person(string name, int age){
this->name = name;
this->age = age;
}
void setPerson(string name, int age){
this->name = name;
this->age = age;
}
string sayHello(){
return name + " : " + to_string(age);
};
};
void setPerson(Person* person){
//delete person;
// new Person("tom", 35);
// Person p("TOM", 35);
// person = &p;
person->setPerson("TOM", 35);
};
int main(){
Person person = Person("JIM", 33);
setPerson(&person);
string result = person.sayHello();
cout << result << endl;
//delete person;
return 0;
}
结果如下,这个经常在Java的八股文中提到,实际上就是对指针的使用,只不过Java的对象都分配至堆中(因为GC,发展了很多代)
TOM : 35
常量指针
实际上就是指针,指向常量的指针,就跟函数指针和指针函数的区别类似,是指针,意味着内存地址是可以修改的,指向的常量,意味着内存地址的值是不可修改的
const int*按照从先到后解析,表示是一个指针,使用常量修饰符的指针(跟Golang相反)
这个与Java和Golang不一样,在Java和Golang没有常量指针的设计,或者说没有限制指针只能指向常量。
指针常量
顾名思义:int* const 表示指针修饰常量,指针是常量,表示指针指向的内存地址不能修改,但是指针指向内存地址的值可以修改。在Java里面比如final List<String> list,在Golang限制使用指针类型为常量修饰。
报错与上面刚刚相反,可以修改值,但是不能修改地址 。
引用
引用的本质就是指针常量,就是上面的简化写法。
常量引用
这个就类似Golang了,常量不允许修改值。
总结
实际上语言学多了,设计都差不多,只不过出于不同的能力考虑,功能就有额外的区别,所以就会有xx语言适合xx开发的说法,在实际运用中,可以一边做项目一边学习。比如笔者最近想看明白JDK的底层实现和K8S的一些ebpf的内容,就需要学习C++,不过C++的关键字是真多,而且语法很细,远超其他语言。比如指针,可能就是因为C语言没有细化指针,而C++具体化了。