文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++函数返回指针和引用的坑

2024-11-30 04:59

关注

而今天我们再来看看在C++新手们针对指针和引用的使用经常犯的错误。

函数返回指针

在C++中针对一个函数返回指针的实现方式一般有三种:

1.返回一个变量的地址

例如以下代码:

// 返回int指针地址
int * funTest(){
    int a = 101;
    return &a;
}

int main(int argc, const char *argv[]) {
    int *a = funTest();
    std::cout << "a的值:" << *a << std::endl;
    return 0;
}

以上代码在笔者的电脑上运行就直接报错崩溃了,崩溃信息:

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

上面的代码返回一个局部变量a的地址,这个变量a紧在函数funTest内有效,当函数funTest结束了,变量a的生命周期也就结束了, 此时变量a所占用的内存空间将被释放,因此返回的指针地址将会被指向一个未知数,后续再使用这个指针是未定义的行为,可能会导致程序崩溃或者出现其他异常。

针对这样的危险代码行为,其实编辑器也已经给出了警告,所以说在开发过程中也不要以为的忽略警告哦。

为了杜绝此类行为的发生,还可以使用笔者之前的介绍的代码质量检测工具cppcheck进行检测,在开发过程中直接划线提醒。

介绍一款CPP代码bug检测神器。

2.返回一个使用static修饰的变量地址

我们修改一下funTest函数的变量a,使用static关键字修饰一下:

// 返回int指针地址
int * funTest(){
    static int a = 101;
    return &a;
}

int main(int argc, const char *argv[]) {
    int *a = funTest();
    std::cout << "a的值:" << *a << std::endl;
    return 0;
}

运行发现程序并没有崩溃,而且是正确打印出了变量a的值。这是因为 使用static 表示将这个变量存储到全局区(static静态区), 此时就不受栈区管控,当函数funTest执行完毕后,变量a依然存在,不会存在前面所说的变量地址被释放的问题。

3.使用动态分配内存new关键字

int * funTest(){
    //动态分配的内存空间,手动delete后才会释放
    int* a = new int(101) ;
    return a;
}

int main(int argc, const char *argv[]) {
    int *a = funTest();
    std::cout << "a的值:" << *a << std::endl;
    return 0;
}

上述代码不会崩溃,也能正常运行,但是存在一个隐患就是返回的指针变量a如果忘记调用delete则会造成内存泄露, 这就引发了一个指针变量谁维护销毁的问题。一般默认规则是谁开发维护。

因此,针对这样的场景,笔者的建议是智能指针你值得拥有...

函数返回一个引用

我们看看以下返回一个引用的例子代码:

int & funTest(){
    //动态分配的内存空间,手动delete后才会释放
    int a = 101 ;
    return a;
}

int main(int argc, const char *argv[]) {
    int a = funTest();
    std::cout << "a的值:" << a << std::endl;
    return 0;
}

笔者在CLion上测试也是直接崩溃了,原因也是和上面所说的返回一个局部变量的地址一样, 都是因为函数funTest结束后,变量a的生命周期结束了, 变量a也就是被释放了,再返回它的引用的话就是未定义的。至于为什么它们的原因是一样的呢?因为所谓引用,可以简单地理解为引用其实就是带const修饰的指针。

那么针对这个问题该如何修正呢?首先使用static关键字肯定是可以的。那么使用动态内存new的方式行不行呢?答案也是可行的,但是需要注意的一点就是如果一个引用 的值来源于一个指针,后来这个指针被delete掉了,那么再使用这个引用也是会造成崩溃的...

如何返回一个数组

那么问题来了,举一反三,如果想通过一个函数返回一个数组那该如何实现呢?

众所周知,C++是不允许直接返回一个数组的,如果您想要从函数返回一个一维数组,您必须声明一个返回指针的函数。

例如下面的写法是编译不通过的:

// 无法编译通过,不能返回一个数组
int[] funTest(){
    int myArray[3] = {1, 2, 3};
    return myArray;
}

正确的写法应该是:

int* funTest(){
    static int myArray[3] = {1, 2, 3};
    return myArray;
}

因而可以看出,其实返回一个数组的函数所遇到的坑其实就转换成了返回一个指针的函数所遇到的坑,这些坑的举例就如前面所说...

来源:思想觉悟内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯