浅析C++指针与引用,栈传递的关系

目录

前言

C++

堆指针

栈指针

常量指针

指针常量

引用 

 常量引用

总结


前言

目前做了很多项目,接触到各种语言,基本上用什么学什么,语言的边际就会很模糊,实际上语言的设计大同小异,只是语言具备各自的特性区别。其中一个重要的概念是指针,这个在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++具体化了。

猜你喜欢

转载自blog.csdn.net/fenglllle/article/details/129111000
今日推荐